Home > Article > Backend Development > Tutorial on setting up and testing Socket server in PHP
This article mainly shares with you the tutorial on how to build and test the Socket server in PHP. I hope it can help you.
1. Ideas for building a socket server
1) Purpose: Understand the working mechanism of the socket server
2) Idea: Create a socket -> Add the socket to the connection pool -> Process receiving information -> Handshake action -> Send information
Note: Copy to php file and run directly from the command line, no other support is required
Special note: In order to transmit Chinese _sendMsg, json_encode() was done
<?php/** * Socket服务器 * @author wuchangliang 2018/1/17 */class SocketServer{ private $sockets; //连接池 private $master; private $handshake; /** * @param $address * @param $port */ public function run($address, $port) { //配置错误级别、运行时间、刷新缓冲区 echo iconv('UTF-8', 'GBK', "欢迎来到PHP Socket测试服务。 \n"); error_reporting(0); set_time_limit(0); ob_implicit_flush(); //创建socket $this->master = $this->_connect($address, $port); $this->sockets[] = $this->master; //运行socket while (true) { $sockets = $this->sockets; $write = NULL; $except = NULL; socket_select($sockets, $write, $except, NULL); //$write,$except传引用 foreach ($sockets as $socket) { if ($socket == $this->master) { $client = socket_accept($socket); $this->handshake = false; if ($client) { $this->sockets[] = $client; //加入连接池 } } else { //接收信息 $bytes = @socket_recv($socket, $buffer, 2048, 0); if ($bytes <= 6) { $this->_disConnect($socket); continue; }; //处理信息 if (!$this->handshake) { $this->_handshake($socket, $buffer); } else { $buffer = $this->_decode($buffer); $this->_sendMsg($buffer, $socket); } } } } } /** * 创建socket连接 * @param $address * @param $port * @return resource */ private function _connect($address, $port) { //创建socket $master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n"); socket_bind($master, $address, $port) or die("socket_bind() failed: reason: " . socket_strerror(socket_last_error($master)) . "\n"); socket_listen($master, 5) or die("socket_listen() failed: reason: " . socket_strerror(socket_last_error($master)) . "\n"); return $master; } /** * 握手动作 * @param $socket * @param $buffer */ private function _handshake($socket, $buffer) { //握手动作信息 $buf = substr($buffer, strpos($buffer, '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"; //记录握手动作 socket_write($socket, $new_message, strlen($new_message)); $this->handshake = true; } /** * 断开socket连接 * @param $socket */ private function _disConnect($socket) { $index = array_search($socket, $this->sockets); socket_close($socket); if ($index >= 0) { array_splice($this->sockets, $index, 1); } } /** * 发送信息 * @param $buffer * @param $client */ private function _sendMsg($buffer, $client) { $send_buffer = $this->_frame(json_encode($buffer)); foreach ($this->sockets as $socket) { if ($socket != $this->master && $socket != $client) { //广播发送(除了自己) socket_write($socket, $send_buffer, strlen($send_buffer)); } } } /** * 解析数据帧 * @param $buffer * @return null|string */ private 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; } /** * 处理返回帧 * @param $buffer * @return string */ private function _frame($buffer) { $len = strlen($buffer); if ($len <= 125) { return "\x81" . chr($len) . $buffer; } else if ($len <= 65535) { return "\x81" . chr(126) . pack("n", $len) . $buffer; } else { return "\x81" . char(127) . pack("xxxxN", $len) . $buffer; } }}$sc = new SocketServer();$sc->run('127.0.0.1', 2046);
3. Client code
Note: Copy directly to html, and the above php file Just stay in the same folder, pay special attention to the two layers of parse parsed by onmessage
<!DOCTYPE html><html><head> <meta charset="utf-8" /> <title>WebSocket Test</title> <script language="javascript"type="text/javascript"> websocket = new WebSocket('ws://127.0.0.1:2046/'); websocket.onopen = function(evt) { console.log('connect'); websocket.send('{"data":"您好,世界!"}'); }; websocket.onclose = function(evt) { console.log('onclose'); console.log(evt); }; websocket.onmessage = function(evt) { console.log('onmessage'); if (evt.data) { console.log(JSON.parse(JSON.parse(evt.data))); } }; websocket.onerror = function(evt) { console.log('onerror'); console.log(evt); }; function sendMsg(){ var sendData = { 'data': document.getElementById('name').value}; websocket.send(JSON.stringify(sendData)); } </script></head><body> <h2>WebSocket Test</h2> <input type="text" name="name" id="name" /> <a href="javascript:;" onclick="sendMsg()">点击发送</a></body></html>
4. Test example
Related recommendations:
How to use PHP to implement Socket server
Send and receive data to socket server in PHP_PHP tutorial
javascript - How to configure WebSocket server, using SegmentFault
The above is the detailed content of Tutorial on setting up and testing Socket server in PHP. For more information, please follow other related articles on the PHP Chinese website!