代码依赖
服务端代码
<?php
require __DIR__ . '/Autoloader.php';
use Workerman\Worker;
$ws_worker = new Worker("websocket://0.0.0.0:9091");
// 启动1个进程对外提供服务
$ws_worker->count = 1;
$clients = [];
// 当收到客户端发来的数据后返回hello $data给客户端
$ws_worker->onMessage = function($connection, $data)
{
global $clients;
echo $data.PHP_EOL;
if (preg_match('/^login:(\w{3,20})/i', $data,$result)) {
if (!array_key_exists($connection->getRemoteIp().':'.$connection->getRemotePort(), $clients)) {
$clients[$connection->getRemoteIp().':'.$connection->getRemotePort()] = ['fd'=>$connection->getRemoteIp().':'.$connection->getRemotePort(),'name'=>$result[1],'conn'=>$connection];
$connection->send("notice:success");//
$connection->send("msg:welcome back ".$result[1]);
$allUser = "user:".json_encode(array_column($clients, 'name','fd'));
foreach ($clients as $value) {
$value['conn']->send($allUser);
}
}
} else if(preg_match("/^msg:(.*?)/isU",$data,$msgset)) {//代表 是客户端发送普通消息
if(array_key_exists($connection->getRemoteIp(),$clients)) //必须已经认证过得客户端
{
echo "get msg :".$msgset[1];
}
} else if (preg_match("/^chat:\<(.*?)\>:(.*?)/isU",$data,$msgset)) {
var_dump($msgset);
$ipp = $msgset[1];
$msg = $msgset[2];
if (array_key_exists($ipp, $clients)) {
$clients[$ipp]['conn']->send("msg:".$msg);
}
}
$connection->onClose=function ($connection)//客户端主动关闭
{
global $clients;
unset($clients[$connection->getRemoteIp().':'.$connection->getRemotePort()]);
$allUser = "user:".json_encode(array_column($clients, 'name','fd'));
foreach ($clients as $value) {
$value['conn']->send($allUser);
}
};
};
// 运行worker
Worker::runAll();
客户端代码
<!DOCTYPE html>
<html>
<head>
<title>chat room</title>
<script type="text/javascript">
// WebSocket 构造函数
var ws,name,isLogin=false;;
function connection(){
if (name.length == 0) {
alert('please input u name');return;
}
ws = new WebSocket("ws://127.0.0.1:9091");
ws.onopen = onopen; //指定连接成功后的回调函数
ws.onmessage = onmessage; // 指定收到服务器数据后的回调函数
ws.onclose = function() { //指定连接关闭后的回调函数
console.log("连接关闭,定时重连");
closed();
};
ws.onerror = function() {
console.log("出现错误");
};
}
function onopen(){
var login_msg = 'login:'+name;
ws.send(login_msg);
}
function onmessage(evt){ // 服务器数据可能是文本,也可能是二进制数据(blob对象或Arraybuffer对象)
console.log( "Received Message: " + evt.data);
var getMsg = evt.data;
if(/^notice:success$/.test(getMsg)) //服务器验证通过,后面做任何发送操作
{
isLogin=true;
}
else if(/^msg:/.test(getMsg)) //代表是普通消息
{
//<p>xxxxooo</p>
var p=document.createElement("P");
p.innerHTML="<span>收到消息</span>"+getMsg.replace("msg:","");
document.getElementById("txtcontent").appendChild(p);
} else if (/^user:/.test(getMsg)) {
var obj = document.getElementById('alluser');
obj.length=0;
obj.add(new Option('please select',''));
var alluser = eval('(' +getMsg.replace("user:","")+ ')');
for(user in alluser){
console.log(user);
console.log(alluser[user]);
obj.add(new Option(alluser[user],user));
}
}
else
{
}
}
function sendText(){
if (!isLogin) {
alert("请先服务器验证");
return;
}
var msg=document.getElementById("txtmsg").value;
var listusers = document.getElementById('alluser');
var toUser = listusers.options[listusers.selectedIndex].value;
if (toUser == '') {
ws.send("msg:"+msg); //用于向服务器发送数据
} else {
var toUserName = listusers.options[listusers.selectedIndex].innerHTML;
ws.send("chat:<"+toUser+">:"+msg);
}
//在div 中显示我们的行为
var p = document.createElement("P");
p.innerHTML="<span>发送消息</span>"+msg
document.getElementById("txtcontent").appendChild(p);
}
function checkstatus(){ //返回实例对象的当前状态,共有四种
// CONNECTING:值为0,表示正在连接。
// OPEN:值为1,表示连接成功,可以通信了。
// CLOSING:值为2,表示连接正在关闭。
// CLOSED:值为3,表示连接已经关闭,或者打开连接失败
if (!isLogin) {
alert("请先服务器验证");
return;
}
alert(ws.readyState);
}
function closed(){
if (!isLogin) {
alert("请先服务器验证");
return;
}
ws.close();
}
</script>
</head>
<body>
<form>
<table>
<tr>
<th>message</th>
<th><div id="txtcontent" style="width: 320px;height: 200px;border-style: solid;border-width: 1px;border-color: #000;"></div></th>
</tr>
<tr>
<th>聊天内容:</th>
<th><input type="text" name="message" id="txtmsg"></th>
</tr>
<tr>
<th>当前用户:</th>
<th><input type="text" name="name" id="name" disabled="true"></th>
</tr>
<tr>
<th>聊天对象:</th>
<th>
<select id="alluser">
<option value=''>所有人</option>
</select>
</th>
</tr>
<tr>
<th><button type="button" onclick="sendText()">send</button></th>
<th><button type="button" onclick="checkstatus()">status</button></th>
</tr>
<tr>
<th><button type="button" onclick="connection()">connection</button></th>
<th><button type="button" onclick="closed()">closed</button></th>
</tr>
</table>
</form>
</body>
<script type="text/javascript">
// 输入姓名
function show_prompt(){
name = prompt('输入你的名字:', '');
if(!name || name=='null'){
name = '游客';
}
document.getElementById('name').value = name;
}
show_prompt();
</script>
</html>
运行截图