美文网首页
websocket和php 简单解释和应用

websocket和php 简单解释和应用

作者: 南苑bert | 来源:发表于2020-04-09 17:23 被阅读0次

不会练习 QQ:2817228206

  1. 首先我们要知道http是什么? 为什么要有socket,socket和http的区别在那里


    image.png

我们知道 http1.0 只有简单的request和response,到了1.1 才有了改变,一般的请求都是走3次握手和4次挥手

第一次握手:起初两端都处于CLOSED关闭状态,Client将标志位SYN置为1,随机产生一个值seq=x,并将该数据包发送给Server,Client进入SYN-SENT状态,等待Server确认;

第二次握手:Server收到数据包后由标志位SYN=1得知Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=x+1,随机产生一个值seq=y,并将该数据包发送给Client以确认连接请求,Server进入SYN-RCVD状态,此时操作系统为该TCP连接分配TCP缓存和变量;

第三次握手:Client收到确认后,检查ack是否为x+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=y+1,并且此时操作系统为该TCP连接分配TCP缓存和变量,并将该数据包发送给Server,Server检查ack是否为y+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client和Server就可以开始传输数据。

4次挥手
起初A和B处于ESTABLISHED状态——A发出连接释放报文段并处于FIN-WAIT-1状态——B发出确认报文段且进入CLOSE-WAIT状态——A收到确认后,进入FIN-WAIT-2状态,等待B的连接释放报文段——B没有要向A发出的数据,B发出连接释放报文段且进入LAST-ACK状态——A发出确认报文段且进入TIME-WAIT状态——B收到确认报文段后进入CLOSED状态——A经过等待计时器时间2MSL后,进入CLOSED状态。

前端

var ws = new WebSocket("ws://127.0.0.1:17122");
    //握手监听函数
    ws.onopen=function(){
         //状态为1证明握手成功,然后把client自定义的名字发送过去
        if(so.readyState==1){
             //握手成功后对服务器发送信息
         so.send('type=add&ming='+n);
        }
    }
    //错误返回信息函数
    ws.onerror = function(){
        console.log("error");
    };
    //监听服务器端推送的消息
    ws.onmessage = function (msg){
        console.log(msg);
    }
     
    //断开WebSocket连接
    ws.onclose = function(){
        ws = false;
    }

php tools.php

<?php
  //解码数据
  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 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;
}
 
 
// encode
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;
}

php server.php


<?php
    include_once("tools.php");
    $address = "127.0.0.1";
    $port = 20000; //调试的时候,可以多换端口来测试程序!
     
    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);
     
     
    while(true){
        // 建立连接
        $msgsock = socket_accept($sock);
        // 读取数据  客户端发过来的
        $buf = socket_read($msgsock, 8192); 
        
        // 响应加密
        $response = hand_shake($buf);

        // 发送响应
        socket_write($msgsock,$response,strlen($response)); 
     
        //正式开始通信...
        $buf = socket_read($msgsock, 8192); //获取前端发送的消息
         if(unmask($buf)==1){
            socket_write($msgsock, mask(json_encode(['msg'=>true])), strlen($response_text));  
         }


         if(unmask($buf)!=1){

          //一旦编码出问题,就是返回空,又不报错
          $msg = '[{
            "Addr": "/ip4/95.179.192.99/tcp/10001",
            "Peer": "QmQFy5XWmtZ7U2nZu198qYW8LefvrBK3Y9b3V1MqUfuoRT",
            "Latency": "",
            "Muxer": "你好",
            "Direction": 0,
            "Streams": null
        }]';

        $response_text = mask($msg);
        socket_write($msgsock, $response_text, strlen($response_text));
    }
        //  socket_close($msgsock);
    };

    
    // socket_close($sock);
   

相关文章

网友评论

      本文标题:websocket和php 简单解释和应用

      本文链接:https://www.haomeiwen.com/subject/ipmvphtx.html