websocket.php后端的设置:
- php.ini需要开启sockets扩展;
- websocket需要CLI(命令行工具)启动服务端文件服务:
php websocket.php
- websocket.php代码
$address = "127.0.0.1"; $port = 9090; //调试的时候,可以多换端口来测试程序! 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: $buf\n"; $response = hand_shake($buf); socket_write($msgsock, $response, strlen($response)); //发送响应 //开始通信... $buf = socket_read($msgsock, 8192); //获取前端发送的消息 //返回json数据; if (unmask($buf) == 'getPeerInfo') { $msg = '[ { "vid": "1", "vname": "杨过", "vdata": "20.00", "vtask": "70.00" }, { "vid": "2", "vname": "小龙女", "vdata": "40.00", "vtask": "100.00" }, { "vid": "3", "vname": "郭靖", "vdata": "40.00", "vtask": "100.00" }, { "vid": "4", "vname": "黄蓉", "vdata": "30.00", "vtask": "100.00" }, { "vid": "5", "vname": "欧阳锋", "vdata": "90.00", "vtask": "100.00" }, { "vid": "6", "vname": "洪七公", "vdata": "90.00", "vtask": "100.00" }, { "vid": "7", "vname": "黄老邪", "vdata": "68.00", "vtask": "90.00" }, { "vid": "8", "vname": "一灯大师", "vdata": "30.00", "vtask": "79.00" }, { "vid": "9", "vname": "老顽童", "vdata": "89.00", "vtask": "98.00" }, { "vid": "10", "vname": "郭襄", "vdata": "69.00", "vtask": "96.00" }]'; $response_text = mask($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, "\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 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 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; }
亟需解决的三个问题:
- 如何保持websocket的长连接;
- 如何让websocket自动推送信息;
- 如何websocket连接MySql数据库;
Done!