- 引入socket.io
composer require “workerman/phpsocket.io”
- 服务代码server.php 基于thinkphp框架
php server.php start //启动服务命令
// 加载基础文件
require __DIR__ . '/../thinkphp/base.php';
use PHPSocketIO\SocketIO;
use Workerman\Worker;
// 执行应用并响应(绑定)
//Container::get('app')->bind('socketio/Server')->run()->send();
// 在2021端口创建服务
$io = new SocketIO(2021);
$io->on('connection', function($socket)use($io){
var_dump($socket->request->_query);
var_dump($socket->id);
$socket->on('chat message', function($msg)use($io){
$io->emit('chat message', $msg);
});
$socket->on('broadcast', function($msg)use($io){
var_dump($msg);
$msg = json_decode($msg,true);
var_dump($msg);
$io->to($msg['fid'])->emit('sendMsg', ['event'=>'broadcast','data'=>$msg['data']]);
});
// 监听到新的客户端连接即在服务端输出'new connection'
echo 'new connection'."\n";
// 并向服务端发送'连接成功'
//$socket->emit('success', '连接成功123131');
// 服务端发送消息过来
$socket->on('sendMsg', function($msg)use($io,$socket){
// 在服务端输出消息
echo $msg."\n";
// 在收到的消息前面拼接'收到'后向客户端发送回去
//$io->to($socket->id)->emit('sendMsg', '收到"'.$msg.'"');
$io->emit('sendMsg', '收到"'.$msg.'" fid='.$socket->id);
// 将接受到的消息存储到数据库
$data['msg'] = $msg;
//Db::table('msg')->insert($data);
});
});
// 启动服务
Worker::runAll();
- 前端客户端
<script src='https://cdn.bootcss.com/socket.io/2.0.3/socket.io.js'></script>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script>
// 如果服务端不在本机,请把127.0.0.1改成服务端ip
var socket = io('http://192.168.153.130:2021');
//var socket = io.connect('http://192.168.153.130:2021',);
// 当连接服务端成功时触发connect默认事件
socket.on('connect', function(msg){
console.log('connect success');
});
socket.on('success', function(msg){
// 连接后弹出服务端返回的消息'连接成功'
console.log('连接成功:'.msg);
//alert(msg);
});
socket.on('sendMsg', function(msg){
// 将服务端返回的消息输出到控制台
console.log(msg);
});
// 向服务端发送消息
$('#send').on('click', function(){
var text = $('#msg').val();
socket.emit('sendMsg', text);
// alert(text);
})
</script>
- php作为socket客户端,连接websocket服务
composer require “roysegall/php_socket-io_client”
ps 有很多类似的包,可就是无法连接,于是改造了一下这个包,终于可以了。【失败大致是理解不够!!】
public function ceshi(){
$result = $this->send('localhost', 2021,'broadcast', json_encode(['fid'=>'3942b66504e2d741048b1644','data'=>'3942b66504e2d741048b1644 '.date('Y-m-d H:i:s')]));
var_dump($result);die;
}
/**
* @param null $host - $host of socket server
* @param null $port - port of socket server
* @param string $action - action to execute in sockt server
* @param null $data - message to socket server
* @param string $address - addres of socket.io on socket server
* @param string $transport - transport type
* @return bool
*/
public function send($host = null, $port = null, $action= "message", $data = null, $address = "/socket.io/?EIO=2", $transport = 'websocket')
{
$fd = fsockopen($host, $port, $errno, $errstr);
if (!$fd) {
return false;
} //Can't connect tot server
$key = $this->generateKey();
$out = "GET $address&transport=$transport HTTP/1.1\r\n";
$out.= "Host: http://$host:$port\r\n";
$out.= "Upgrade: WebSocket\r\n";
$out.= "Connection: Upgrade\r\n";
$out.= "Sec-WebSocket-Key: $key\r\n";
$out.= "Sec-WebSocket-Version: 13\r\n";
$out.= "Origin: *\r\n\r\n";
fwrite($fd, $out);
// 101 switching protocols, see if echoes key
$result= fread($fd,10000);
preg_match('#Sec-WebSocket-Accept:\s(.*)$#mU', $result, $matches);
$keyAccept = trim($matches[1]);
$expectedResonse = base64_encode(pack('H*', sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$handshaked = ($keyAccept === $expectedResonse) ? true : false;
if ($handshaked){
fwrite($fd, $this->hybi10Encode('42["' . $action . '", "' . addslashes($data) . '"]'));
$content = '';
while(!feof($fd)){
stream_set_timeout($fd, 1);
$content .= fread($fd, 1024);
$info = stream_get_meta_data($fd);
if ($info['timed_out']) {
break;
}
}
//fread($fd,1000000);
fclose($fd);
return true;
} else {return false;}
}
private function generateKey($length = 16)
{
$c = 0;
$tmp = '';
while ($c++ * 16 < $length) { $tmp .= md5(mt_rand(), true); }
return base64_encode(substr($tmp, 0, $length));
}
private function hybi10Encode($payload, $type = 'text', $masked = true)
{
$frameHead = array();
$payloadLength = strlen($payload);
switch ($type) {
case 'text':
$frameHead[0] = 129;
break;
case 'close':
$frameHead[0] = 136;
break;
case 'ping':
$frameHead[0] = 137;
break;
case 'pong':
$frameHead[0] = 138;
break;
}
if ($payloadLength > 65535) {
$payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);
$frameHead[1] = ($masked === true) ? 255 : 127;
for ($i = 0; $i < 8; $i++) {
$frameHead[$i + 2] = bindec($payloadLengthBin[$i]);
}
if ($frameHead[2] > 127) {
$this->close(1004);
return false;
}
} elseif ($payloadLength > 125) {
$payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);
$frameHead[1] = ($masked === true) ? 254 : 126;
$frameHead[2] = bindec($payloadLengthBin[0]);
$frameHead[3] = bindec($payloadLengthBin[1]);
} else {
$frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;
}
foreach (array_keys($frameHead) as $i) {
$frameHead[$i] = chr($frameHead[$i]);
}
if ($masked === true) {
$mask = array();
for ($i = 0; $i < 4; $i++) {
$mask[$i] = chr(rand(0, 255));
}
$frameHead = array_merge($frameHead, $mask);
}
$frame = implode('', $frameHead);
for ($i = 0; $i < $payloadLength; $i++) {
$frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
}
return $frame;
}