社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
根据①实现了简单的前后端交互,但是,参考②和③5,我针对我的情况成功的增加了两点:
1.允许服务器返回JSON格式的数据
2.获取客户端发送的数据(这一条有许多教程都实现了,比如拿聊天室,或者这篇教程的大佬
再开始之前,先确认,你的php否开启了sockets扩展:
websocket.php:
<?php
$address = "127.0.0.1";
$port = 9999; //调试的时候,可以多换端口来测试程序!
set_time_limit(0);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_block($sock);
socket_bind($sock, $address, $port);
socket_listen($sock, 4);
do
{
echo "Waiting for Connection...n";
$msgsock = socket_accept($sock);
echo "Waiting for Request...n";
$buf = socket_read($msgsock, 8192); //读取请求
echo "Request Received: $bufn";
$response = hand_shake($buf);
socket_write($msgsock,$response,strlen($response)); //发送响应
//正式开始通信...
$buf = socket_read($msgsock, 8192); //获取前端发送的消息
//这里我用了③中的编码和解码方法mask和umaske,原来的无法正确的接收到客户端发的信息,乱码,
//而且无法将json数据编码发送给前端,我是没成功。
if (unmask($buf) == 'getPeerInfo') {
//我要返回的json数据
$msg = '[{
"Addr": "/ip4/95.179.192.99/tcp/10001",
"Peer": "QmQFy5XWmtZ7U2nZu198qYW8LefvrBK3Y9b3V1MqUfuoRT",
"Latency": "",
"Muxer": "你好",
"Direction": 0,
"Streams": null
},
{
"Addr": "/ip4/95.216.192.206/tcp/4001",
"Peer": "QmZyVchYnNcRdCcikT29GNFGZscBdWeJ6BaWdTxZmm2V5M",
"Latency": "",
"Muxer": "你好",
"Direction": 0,
"Streams": null
},
{
"Addr": "/ip4/98.11.199.27/tcp/39853",
"Peer": "QmVvP46C4wqyKt4aGBsf9gsr482rnf65ZxP1Hh8v4xPgdD",
"Latency": "",
"Muxer": "",
"Direction": 0,
"Streams": null
},
{
"Addr": "/ipfs/QmRv1GNseNP/p2p-circuit",
"Peer": "QmVCgCcoeB9fqoat8jJS8XDxqEnVizNzTbz8JsM2NCUZcY",
"Latency": "",
"Muxer": "",
"Direction": 0,
"Streams": null
},
{
"Addr": "/ipfs/QmRv1GNseNP/p2p-circuit",
"Peer": "QmSEzrFkZQCN138uTHeJaBBH2GQ3Kq3XnUAx2iAMneTQsZ",
"Latency": "",
"Muxer": "",
"Direction": 0,
"Streams": null
}]';
$response_text = mask(json_encode($msg));
socket_write($msgsock, $response_text, strlen($response_text));
}else{
//这里不建议用array,因为json_encode之后出现空值,可能是编码问题。
//一旦编码出问题,就是返回空,又不报错
$msg = '{"error:"Invalid method"}';
$response_text = mask(json_encode($msg));
socket_write($msgsock, $response_text, strlen($response_text));
};
socket_close($msgsock);
} while (true);
socket_close($sock);
function hand_shake($buf){
$buf = substr($buf,strpos($buf,'Sec-WebSocket-Key:')+18);
$key = trim(substr($buf,0,strpos($buf,"rn")));
$new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
$new_message = "HTTP/1.1 101 Switching Protocolsrn";
$new_message .= "Upgrade: websocketrn";
$new_message .= "Sec-WebSocket-Version: 13rn";
$new_message .= "Connection: Upgradern";
$new_message .= "Sec-WebSocket-Accept: " . $new_key . "rnrn";
return $new_message;
}
//解码数据
function unmask($text) {
$length = ord($text[1]) & 127;
if($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
}
elseif($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
}
else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
//function code($msg){
// $msg = preg_replace(array('/r$/','/n$/','/rn$/',), '', $msg);
// $frame = array();
// $frame[0] = '81';
// $len = strlen($msg);
// $frame[1] = $len<16?'0'.dechex($len):dechex($len);
// $frame[2] = ord_hex($msg);
// $data = implode('',$frame);
// return pack("H*", $data);
// }
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCn', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCNN', $b1, 127, $length);
return $header.$text;
}
//function ord_hex($data) {
// $msg = '';
// $l = strlen($data);
// for ($i= 0; $i<$l; $i++) {
// $msg .= dechex(ord($data{$i}));
// }
// return $msg;
//}
?>
websocket.html:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h3>WebSocket协议的客户端程序</h3>
<button id="btConnect">连接到WS服务器</button>
<button id="btSendAndReceive">向WS服务器发消息并接收消息</button>
<button id="btClose">断开与WS服务器的连接</button>
<div id="val"></div>
<script>
var wsClient = null; //WS客户端对象
btConnect.onclick = function(){
//连接到WS服务器,注意:协议名不是http!
wsClient = new WebSocket('ws://127.0.0.1:9999');
wsClient.onopen = function(){
console.log('WS客户端已经成功连接到服务器上')
}
}
btSendAndReceive.onclick = function(){
//向WS服务器发送一个消息
wsClient.send('getPeerInfo'); //发送的消息
console.log('WS客户端向WS服务器发送一个消息')
//接收WS服务器返回的消息
wsClient.onmessage = function(e){
console.log('WS客户端接收到一个服务器的消息:'+ JSON.parse(e.data)); //注意加json解析
val.innerHTML=JSON.parse(e.data);
}
}
btClose.onclick = function(){
//断开到WS服务器的连接
wsClient.close(); //向服务器发消息,主动断开连接
wsClient.onclose = function(){
//经过客户端和服务器的四次挥手后,二者的连接断开了
console.log('到服务器的连接已经断开')
}
}
</script>
</body>
</html>
1. 在你Apache访问目录,我的在(apache的htdocs ),打开cmd(shift+右键,能看到在此目录打开powershell/命令行终端)
运行:php websocket.php
这样就可以开启了socket线程,等待客户端连接了。
2.浏览器访问:http://localhost/websocket_2.html,并F12打开浏览器控制台
3.先点击,连接服务器,在发送消息并接收,此后这次回话就结束了,所以你点断开没用。
至此已成功实现根据前端发送的数据,判断返回相应的json数据。但还有几点讨论跟大家说一下:
1.你想一开始就初始化一个与服务器端的连接,可以参考④中的写法:
将:
wsClient = new WebSocket('ws://127.0.0.1:9999');
wsClient.onopen = function(){
console.log('WS客户端已经成功连接到服务器上')
}
写在最外层:
但是有个缺陷:你运行完发送消息之后,如果没有那个点击连接的按钮,那你只能重新刷新页面,因为运行之后就断开连接了。
其实能实现持续发送的,可以参考④,目前我没去改。
2.如果你的json从其他页面传过来,你需要注意编码,在代码中我也有提及,特别对中文,可以先用urlencode,在用urldecode例如我的:
3.未完待续,我会研究下怎么加载页面后,可以直接连续点发送消息,再断开连接操作。。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!