Php websocket example _ PHP Tutorial

Source: Internet
Author: User
Tags key string php websocket nodejs websocket
Php websocket example. This article mainly introduces the example of using websocket in php. if you need a websocket connection, you can refer to the figure below to demonstrate the handshake between the client and the server, this article mainly introduces the example of using websocket in php. For more information, see

The following figure shows the handshake between the client and the server when a websocket connection is established. This part can be easily completed in node, because the net module provided by node has encapsulated socket sockets, developers only need to consider data interaction instead of connection creation. Php does not, from socket connection, establishment, binding, listening, etc., all of which need to be operated by ourselves, so it is necessary to come up with it. ① And ② are actually an HTTP request and response, but what we get during the processing is a string that has not been parsed. For example, the code is as follows: GET/chat HTTP/1.1 Host: server. example. comOrigin: http://www.jb51.com We often see this request. when it comes to the server side, we can directly obtain this information through some code libraries. 1. processing websocket WebSocket connections in php is actively initiated by the client, so everything should proceed from the client. The first step is to parse the Sec-WebSocket-Key string sent from the client. The code is as follows: GET/chat HTTP/1.1 Host: server. example. comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ = Origin: http://www.jb51.com Sec-WebSocket-Protocol: chat, superchatSec-WebSocket-Version: 13 The format of the client request. first, php establishes a socket connection and listens to port information. 1. the establishment of a socket connection refers to the establishment of a socket. I believe that many people who have completed computer networks in the university know the establishment of a connection. The following is a process of establishing a connection: the code is as follows: // Create a 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 with node, the processing in this place is too troublesome. the above lines of code have not been connected, but these codes are something that must be written to build a socket. Because the processing process is a little complicated, I wrote various processing into a class to facilitate management and calling. The code is as follows: // demo. phpClass WS {var $ master; // connect to the server's client var $ sockets = array (); // var $ handshake = false for socket management in different states; // determine whether to shake hands function _ construct ($ address, $ port) {// Create a 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) {// The socket automatically selected for the message. if it is a handshake, the host is automatically selected $ write = NULL; $ response t = NULL; socket_select ($ this-> sockets, $ write, $ response T, NULL); foreach ($ this-> sockets as $ socket) {// connect the client to the host If ($ socket = $ this-> master) {$ client = socket_accept ($ this-> 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, shake hands first to respond // doHandShake ($ socket, $ buffer); echo "shakeHands \ n ";} else {// if the handshake has been made, directly accept the data and process $ buffer = decode ($ buffer); // process ($ socket, $ buffer ); echo "send file \ n" ;}}}} the above code has been debugged by me. it's not a big problem. if you want to test it, you can type php/path/to/demo in the cmd command line. php; of course, the above is just a class. 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 slightly simpler: the code is as follows: var ws = new WebSocket ("ws: // localhost: 4000 "); ws. onopen = function () {console. log ("handshake successful") ;}; ws. onerror = function () {console. log ("error") ;}; run the server code. when the client is connected, we can see: 2. the code for extracting Sec-WebSocket-Key information is as follows: function getKey ($ req) {$ key = null; if (preg_match ("/Sec-WebSocket-Key :(. *) \ r \ n/", $ req, $ match) {$ key = $ match [1];} return $ key;} This is relatively simple, straight The websocket header must contain the Sec-WebSocket-Key, so it is quick to match ~ 3. the code for encrypting the Sec-WebSocket-Key is as follows: function encry ($ req) {$ key = $ this-> getKey ($ req); $ mask = "258eafa5-e914-4710995ca-c5ab0dc85b11 "; return base64_encode (sha1 ($ key. '258eafa5-E914-47DA-95CA-C5AB0DC85B11 ', true);} re-encrypts the string after SHA-1. If the encryption algorithm is incorrect, the client will directly report an error during the verification: 4. response to Sec-WebSocket-Accept code: function dohandshake ($ socket, $ req) {// Obtain the 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); // indicates that the handshake is successful. data is used for receiving data next time. Frame format $ this-> handshake = true;} you must note that each request and corresponding format has an empty row, namely \ r \ n, I lost this item at the beginning of the test and had a long struggle. After the client successfully verifies the key, the onopen function is triggered: 5. the data frame processing code is as follows: // parse the data frame 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;} encoding problems mentioned in the previous article are not described here, php has too many character processing functions, and I don't remember it clearly. here we haven't provided a detailed description of the decoding program, so we can directly return the data sent by the client as is, it can be regarded as a chat room model. The code is as follows: // 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;} // return data function send ($ client, $ msg) {$ msg = $ this-> frame ($ msg ); socket_write ($ client, $ msg, strlen ($ msg);} client code: Code: var ws = new WebSocket ("ws: // localhost: 4000 "); ws. onopen = function () {Console. log ("handshake successful") ;}; ws. onmessage = function (e) {console. log ("message:" + e. data) ;}; ws. onerror = function () {console. log ("error") ;}; ws. send ("Li Jing"); after the connection, the server returns the data as it is: 2. Note Problem 1. for websocket Version problems, the client has the Sec-WebSocket-Version: 13 in the handshake request. this Version ID is an upgraded Version, which is used by browsers. In earlier versions, data encryption is more troublesome. it sends two keys: GET/chat HTTP/1.1 Host: server. example. comUpgrade: websocketConnection: UpgradeOrigin: http://www.jb51.netSec-WebSocket-Protocol : Chat, superchatSec-WebSocket-Key1: xxxxSec-WebSocket-Key2: xxxx if this version (relatively old, no longer in use), you need to get the code through the following method: function encry ($ key1, $ key2, $ l8b) {// Get the numbers preg_match_all ('/([\ d] +)/', $ key1, $ key1_num ); preg_match_all ('/([\ d] +)/', $ key2, $ key2_num); $ key1_num = implode ($ key1_num [0]); $ key2_num = implode ($ key2_num [0]); // Count spacespreg_match_all ('/([] +)/', $ key1, $ key1_spc ); preg_match_all ('/([] + )/ ', $ Key2, $ key2_spc); if ($ key1_spc = 0 | $ key2_spc = 0) {$ this-> log ("Invalid key"); return ;} // Some math $ key1_sec = pack ("N", $ key1_num/$ key1_spc); $ key2_sec = pack ("N", $ key2_num/$ key2_spc ); return md5 ($ keydomainsec. $ key2_sec. $ l8b, 1) ;}you can only use this verification method without limit! Compared to nodeJs websocket operation method: Code: // server program var crypto = require ('Crypto'); var WS = '258eafa5-E914-47DA-95CA-C5AB0DC85B11 '; require ('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 article does not provide data frame parsing code such as decodeFrame. The format of the data frame. parsing is purely physical.

The following figure shows the handshake between the client and the server when a websocket connection is established...

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.