PHP using WebSocket sample _php Tutorial

Source: Internet
Author: User
Tags key string sha1 nodejs websocket
This article mainly introduces PHP using the WebSocket example, the need for friends can refer to the following

Here I draw a diagram showing the handshake part of the WebSocket connection between the client and the server, which can be done very easily in node, because the net module provided by node has already encapsulated the socket socket, and developers only need to use Consider the interaction of the data without having to deal with the establishment of the connection. and PHP does not, from the socket connection, establishment, binding, monitoring, and so on, these need our own to operate, so it is necessary to come out and say. ① and ② are actually an HTTP request and response, but we're dealing with a string that's not parsed. such as: The Code is as follows: Get/chat http/1.1host:server.example.comorigin:http://www.jb51.com We always see the request is this look, when this thing to the server side, We can get this information directly from some code libraries. First, PHP processing WebSocket websocket Connection is initiated by the client, so everything to start from the client. The first step is to parse the Sec-websocket-key string that gets sent to the client. The code is as follows: Get/chat Http/1.1host:server.example.comupgrade:websocketconnection:upgradesec-websocket-key: Dghlihnhbxbszsbub25jzq==origin:http://www.jb51.comsec-websocket-protocol:chat, SuperchatSec-WebSocket-Version: The format of the client request first PHP establishes a socket connection to listen for information on the port. 1. Socket connection establishment about socket socket, I believe that many university computer network people know, the following is a connection to establish the process: the code is as follows://Create a socket socket $master = socket_create (af_inet , Sock_stream, sol_tcp); Socket_set_option ($master, Sol_socket, SO_REUSEADDR, 1); Socket_bind ($master, $address, $port) ; Socket_listen ($master);Compared to node, this place is too cumbersome to handle, the above lines of code are not connected, but the code is to create a socket socket must write something. Because of the complexity of the process, I wrote all sorts of processing into a class that was easy to manage and invoke. The code is as follows://demo.phpclass WS {var $master;//client Var $sockets connected to Server = Array ();//Socket management var $handshake in different states = f Alse; Determine if the handshake function __construct ($address, $port) {//Create a socket socket $this->master = socket_create (Af_inet, Sock_stream, SOL_TCP) or Die ("Socket_create () failed"); Socket_set_option ($this->master, Sol_socket, SO_REUSEADDR, 1) or Die ("Socket_option () failed"); Socket_bind ($this->master, $address, $port) or Die ("Socket_bind () failed"); Socket_listen ($this->master, 2) or Die ("Socket_listen () failed"); $this->sockets[] = $this->master; Debug echo ("Master socket:" $this->master. " \ n "); while (true) {//automatically selects the socket for the message if the handshake is automatically selected by the host $write = null; $except = null; Socket_select ($this->sockets, $write, $exce PT, NULL); foreach ($this->sockets as $socket) {//Connect the host's client if ($socket = = $this->master) {$client = socket_accept ($this-&G T;mASTER); if ($client < 0) {//debug echo "Socket_accept () failed"; continue;} else {//connect ($client); Array_push ($this- sockets, $client); echo "Connect client\n"; }} else {$bytes = @socket_recv ($socket, $buffer, 2048,0), if ($bytes = = 0) return, if (! $this->handshake) {//If there is no handshake, first hold Hand response//dohandshake ($socket, $buffer); echo "shakehands\n"; } else {//If you have already shook hands, accept the data directly and handle $buffer = Decode ($buffer);//process ($socket, $buffer); echo "Send file\n";}} }}}} above this code is I debug, not too much problem, if you want to test, you can type php/path/to/demo.php on the cmd command line; Of course, it's just a class, and if you want to test it, you have to create a new instance. The code is as follows: $ws = new ws (' localhost ', 4000); The client code can be a little simpler: The code is as follows: var ws = new WebSocket ("ws://localhost:4000"), Ws.onopen = function () {Console.log ("handshake succeeded");}; Ws.onerror = function () {Console.log ("error");}; Run the server code, when the client connection, we can see: 2. Extract the Sec-websocket-key information code as follows: function GetKey ($req) {$key = null, if (Preg_match ("/sec-websocket-key: (. *) \r\n/", $req, $m Atch) {$key = $match [1];} return $key;} Here is relatively simple, direct matching, websocket information header must contain SEC-WEBSOCket-key, so we match up also relatively fast ~ 3. The encryption Sec-websocket-key code is as follows: function Encry ($req) {$key = $this->getkey ($req); $mask = " 258eafa5-e914-47da-95ca-c5ab0dc85b11 "; Return Base64_encode (SHA1 ($key. ' 258eafa5-e914-47da-95ca-c5ab0dc85b11 ', True));} The SHA-1 encrypted string is then base64 encrypted again. If the encryption algorithm is wrong, the client will make a direct error when checking the test: 4. The answer sec-websocket-accept code is as follows: function Dohandshake ($socket, $req) {//Get encryption Key $acceptKey = $this->encry ($req); Upgrade = "http/1.1 101 switching protocols\r\n". "Upgrade:websocket\r\n". "Connection:upgrade\r\n". "Sec-websocket-accept:". $acceptKey. "\ r \ n". "\ r \ n"; Write socket Socket_write (socket, $upgrade. chr (0), strlen ($upgrade. chr (0))); The token handshake has succeeded, the next time the data is accepted in the data frame format $this->handshake = true;} It is important to note that each request and the corresponding format, finally there is a blank line, that is, \ r \ n, the beginning of the test to lose this thing, tangled for a half day. When the client successfully checks key, it will trigger the OnOpen function: 5. The Data frame processing code is as follows://Parse Data frame function decode ($buffer) {$len = $masks = $data = $decoded = null; $len = Ord ($buffer [1]) & 127; F ($len = = = 126) {$masks = substr ($buffer, 4, 4); $data = substr ($buffer, 8);} ElSe if ($len = = = 127) {$masks = substr ($buffer, ten, 4), $data = substr ($buffer, +),} else {$masks = substr ($buffer, 2, 4); $data = substr ($buffer, 6); } for ($index = 0; $index < strlen ($data); $index + +) {$decoded. = $data [$index] ^ $masks [$index% 4];} return $decode D;} The coding problems involved here have been mentioned in the previous article, here is not to mention that PHP on character processing function too much, but also remember not particularly clear, here there is no detailed introduction of the decoding program, directly send the data sent back to the client, can be considered a chat room mode bar. The code is as follows://returns the frame information processing function frame ($s) {$a = Str_split ($s, \x81), if (count ($a) = = 1) {return ". Chr" (strlen ($a [0])). $a [0]; } $ns = ""; foreach ($a as $o) {$ns. = "\x81". Chr (strlen ($o)). $o;} return $ns;} Return data function Send ($client, $msg) {$msg = $this->frame ($msg), Socket_write ($client, $msg, strlen ($msg)), client code: code such as Under: var ws = new WebSocket ("ws://localhost:4000"), Ws.onopen = function () {Console.log ("handshake succeeded");}; Ws.onmessage = function (e) {console.log ("message:" + E.data);}; Ws.onerror = function () {Console.log ("error");}; Ws.send ("Li Jing"); Send data after connectivity, the server returns as-is: two, pay attention to question 1. WebSocket version problem the client has sec-websock in the request to the handshakeEt-version:13, this version of the identity, this is an upgrade version, now the browser is the use of this version. While the previous version is more cumbersome in the Data encryption section, it sends two keys: The code is as follows: Get/chat http/1.1host:server.example.comupgrade:websocketconnection: Upgradeorigin:http://www.jb51.netsec-websocket-protocol:chat, Superchatsec-websocket-key1: Xxxxsec-websocket-key2:xxxx If this version (older, is not already in use), you need to obtain the code as follows: function Encry ($key 1, $key 2, $l 8b) {//get the Numbers Preg_match_all ('/([\d]+)/', $key 1, $key 1_num); Preg_match_all ('/([\d]+)/', $key 2, $key 2_num); $key 1_num = implode ($key 1_num[0]), $key 2_num = implode ($key 2_num[0]);//count Spacespreg_match_all ('/([]+)/', $key 1, $ KEY1_SPC);p Reg_match_all ('/([]+)/', $key 2, $key 2_SPC); if ($key 1_spc==0| $key 2_spc==0) {$this->log ("Invalid key"); return;} Some math$key1_sec = Pack ("n", $key 1_num/$key 1_spc), $key 2_sec = Pack ("n", $key 2_num/$key 2_spc); return MD5 ($key 1_sec. $key 2_sec. $l 8b,1);} Only Infinite spit groove this verification way! Compared to NodeJs websocket operation mode: Code as follows://server program var crypto = require (' crypto '); var WS = ' 258eafa5-e914-47da-95ca-c5ab0dc85b11 '; re Quire (' net '). CreateseRVer (function (o) {var key;o.on (' Data ', function (e) {if (!key) {//Handshake key = E.tostring (). Match (/sec-websocket-key: (. +)/) [ 1];key = Crypto.createhash (' SHA1 '). Update (key + WS). Digest (' base64 '); O.write (' http/1.1 101 switching protocols\r\n ') ; O.write (' upgrade:websocket\r\n '); O.write (' connection:upgrade\r\n '); O.write (' sec-websocket-accept: ' + key + ' \ r \ n ') ); O.write (' \ r \ n ');} Else{console.log (e);};}). Listen (8000); 2. Data frame Parsing code This paper does not give the Decodeframe such data frame parsing code, the previous text gives the format of the data frame, the analysis is purely physical activity.

http://www.bkjia.com/PHPjc/740820.html www.bkjia.com true http://www.bkjia.com/PHPjc/740820.html techarticle This article mainly introduces PHP using WebSocket example, the need for friends can refer to below I drew a diagram showing the client and server to establish a websocket connection between the handshake part, this ...

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.