php socket数据 页面显示,做一个php socket 向 websocket 传送数据的简单程序,想了解核心,在帧处理这里我搞不懂,麻烦解释一下...

有三个疑问:

1.连接成功后,我想服务器发送消息,为什么只有第一次服务器会返回信息

2.第一次向服务器发送信息,服务器会返回信息,但是返回的信息是125个字符的,并不是一次返回全部,如图e186cc5e5629bb65b303c0897a156db7.png

3.为什么发汉字多了会报错,服务器直接关闭,发几个字不会72e52a6d327c3de74ad2c0b4ea675acb.png

003d7f3a8980d0c20b61f179eb315c80.png

> 这是服务器代码,php的

set_time_limit(0);

$address = '127.0.0.1';

$port = '231';

if( ($sock = socket_create( AF_INET, SOCK_STREAM, SOL_TCP )) === false ) die( "套接字创建失败:" . socket_strerror(socket_last_error( )) );

if ( ($ok = socket_bind( $sock , $address , $port )) === false ) die( "服务器绑定失败:" . mb_convert_encoding(socket_strerror( socket_last_error( $sock )) , "utf-8","GBK") );

if ( socket_listen($sock, 4) === false ) die( "服务器监听失败:" . socket_strerror( socket_last_error( $sock ) ) );

print_r('服务器开启成功');

while (true){

if (($client = socket_accept($sock)) === false) die( "套接字接收客户端创建失败:" . socket_strerror(socket_last_error( $sock )) );

$buf = socket_read($client, 8192); //读取请求

$response = hand_shake($buf); //跟websocket握手

socket_write($client,$response,strlen($response));//发送响应

//正式开始通信...

$msg = socket_read($client, 8192);

$msg = frame(decode($msg));

socket_write($client, $msg, strlen($msg));

//$msg = code($msg);

//if( socket_write($client,$msg,strlen($msg)) === false ) die("socket_write() failed: reason: " . socket_strerror(socket_last_error()) ."/n"); //发送数据

//else echo'发送信息成功';

//socket_close($client);

}

//socket_close($sock);

function hand_shake($buf){

$buf = substr($buf,strpos($buf,'Sec-WebSocket-Key:')+18);

$key = trim(substr($buf,0,strpos($buf,"\r\n")));

$new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));

$new_message = "HTTP/1.1 101 Switching Protocols\r\n";

$new_message .= "Upgrade: websocket\r\n";

$new_message .= "Sec-WebSocket-Version: 13\r\n";

$new_message .= "Connection: Upgrade\r\n";

$new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";

return $new_message;

}

// 解析数据帧

function decode($buffer) {

$len = $masks = $data = $decoded = null;

$len = ord($buffer[1]) & 127;

if ($len === 126) {

$masks = substr($buffer, 4, 4);

$data = substr($buffer, 8);

} else if ($len === 127) {

$masks = substr($buffer, 10, 4);

$data = substr($buffer, 14);

} else {

$masks = substr($buffer, 2, 4);

$data = substr($buffer, 6);

}

for ($index = 0; $index < strlen($data); $index++) {

$decoded .= $data[$index] ^ $masks[$index % 4];

}

return $decoded;

}

// 返回帧信息处理

function frame($s) {

$a = str_split($s, 125);

if (count($a) == 1) {

return "\x81" . chr(strlen($a[0])) . $a[0];

}

$ns = "";

foreach ($a as $o) {

$ns .= "\x81" . chr(strlen($o)) . $o;

}

return $ns;

}

// 返回数据

function send($client, $msg){

$msg = $this->frame($msg);

socket_write($client, $msg, strlen($msg));

}

?>

前端代码

超迷你简易网页聊天

妈妈爸爸

function $(ele){

return document.getElementById(ele);

}

var ws = new WebSocket("ws://127.0.0.1:231");

ws.onopen = function(){ log("连接服务器成功"); }

ws.onerror = function(){ log("连接服务器失败"); }

ws.onclose = function(){ log("服务器已关闭"); }

$('send').onclick = function(){

ws.send( $('cont').value );

ws.onmessage = function(e){

log('新消息:'+ e.data);

}

}

function log(html){ $('history').value += '->'+html+'\n' ; }

回答

以下内容仅为查阅相关资料后得出的结论,如果错误请指出。

仅作为学习参考,如需用于生产,请选择已有的一些解决方案。

58ed56961aa38e73d6d7a752f090587e.png

问题1:

在完成握手后, socket_read 开始阻塞接受输入,输入完成后发给浏览器后,就又回到了上面的 接受客户端连接,所以 你就只能发送一条消息,如果要想一直发送,就需要把 正式开始通信那一部分放进 while true 里面,让他一直阻塞接受输入。就可以一直发送消息了。

63700413c52c048ca85b10f774edbb55.png

问题2:

关于第二个问题问题,详见RFC 6455

Payload length: 7 bits, 7+16 bits, or 7+64 bits

The length of the "Payload data", in bytes: if 0-125, that is the

payload length. If 126, the following 2 bytes interpreted as a

16-bit unsigned integer are the payload length. If 127, the

following 8 bytes interpreted as a 64-bit unsigned integer (the

most significant bit MUST be 0) are the payload length. Multibyte

length quantities are expressed in network byte order. Note that

in all cases, the minimal number of bytes MUST be used to encode

the length, for example, the length of a 124-byte-long string

can't be encoded as the sequence 126, 0, 124. The payload length

is the length of the "Extension data" + the length of the

"Application data". The length of the "Extension data" may be

zero, in which case the payload length is the length of the

"Application data".

问题3:

发送中文在发送时是对的,但是浏览器在接受到响应后会发生 Could not decode a text frame as UTF-8. 错误。这是服务器在接收数据时被拆分成了几个帧(通常是发送的数据太长,在 socket_read 时被当成了几个帧接收(见2),此时是按照帧进行回复的,因为读取并不一定恰好是一个完整的汉字,就造成了 utf-8 编码错误。)

关于 socket 相关例子请查阅

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值