An example of a simple PHP process plus a socket plus WS

Source: Internet
Author: User

This code is based on the TP framework,

The server-side command line runs PHP index.php Home/ws/start.

Note Change the code

Socket code

<?php

namespace Home\controller;
Use Think\controller;
Use Home\controller\rediscontroller;

Class Wssocketcontroller {

Storage Connection Resources
Private $clients;
Main port
Private $master;
Customer Resources
Private $user;
Private $ip;
Private $port;
Private $redis;

Public function __construct ($socketHandle) {

$this->master = $socketHandle;
$this->clients = Array (' s ' = = $this->master);
$this->redis = Rediscontroller::connect ();
}


Monitor sockets
function Run () {
while (true) {
$read = $this->clients;
Socket_select ($read, $write = null, $except = NULL, NULL);

foreach ($read as $r) {

if ($r = = $this->master) {
Set up a four-step handshake protocol
There is a client new incoming connection coming in
Determine if the server socket is activated
Accept the client and add him to the customer array
$this->clients[] = $newCli = socket_accept ($this->master);
$this->user[] = array (' handle ' =>false);
$pid = Posix_getpid (). ' _ '. Count ($this->user);
$this->redis->sadd (' PID ', $pid);

} else {
An existing connection sends a message to all client data read
Read line break or 1024 bytes
Silent error message Although the client displays an error when disconnecting
$buffer = ";
$data = Socket_recv ($r, $buffer, 2048,0);

Check if the client is disconnected
if ($data < 7) {
Delete Client as Customer array
$this->close ($R);
Continue
}

$k = $this->search ($r);

if ($this->user[$k [' handle '] = = False) {//Only four-step handshake protocol is performed and the browser sends a WS-Protocol request
$this->handshake ($k, $buffer); Returns the WS-Protocol answer

} else {//has already established the WS-Protocol to get messages sent through WS
$pid = Posix_getpid (). ' _ '. Count ($this->user);
$str = $this->uncode ($buffer). ' __ '. $pid;
$this->sendall ($str, $r); Send Message Broadcast

}


}


}
}



}



/*
* Send WS protocol, establish WS-Protocol link
* @param int Socket Index
* @param the content of the request protocol sent by a string ws
*/
Private function Handshake ($k, $buffer) {
Get key and generate a new key
$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));

Return HTTP protocol
$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 ($this->clients[$k], $new _message,strlen ($new _message));
$this->user[$k [' handle '] = true;

return true;

}


/*
* Mass Message
* Content sent @param a string
* @param resource A resource connection to send a message
*/
Private Function Sendall ($STR, $socket) {
Put all this customer in the customer array (except for the first one, which is a listening socket)
foreach ($this->clients as $send _sock) {
If the resource is equal to the server or is equal to its own skip,
if ($send _sock = = $this->master)//| | $send _sock = = $socket
Continue
Send a message to another user
$data = $this->code ($STR);
Socket_write ($send _sock, $data, strlen ($data));
}

}




/*
* Find Socket Resource Index
* @param Resource Socket Resource Index
*
*/
Private Function Search ($sign) {
foreach ($this->user as $k = + $v) {
if ($sign = = $v [' socket ']
return $k;
// }
$k = Array_search ($sign, $this->clients);
return $k;
}


/*
* Disconnect Sockt Connection
* @param resource Socket Resource connection
*/

Privatefunction Close ($sign) {//Disconnect by marking
$k = Array_search ($sign, $this->clients);
Socket_close ($sign); Disconnected connections need to be manually shut down on the server side
unset ($this->user[$k]);
unset ($this->clients[$k]);
}


/*
*
*WS Information decoding
* @param string string
*/
Private Function Uncode ($STR) {
$mask = Array ();
$data = ";
$msg = Unpack (' h* ', $str);
$head = substr ($msg [1],0,2);
if (Hexdec ($head {1}) = = = 8) {
$data = false;
}else if (Hexdec ($head {1}) = = = 1) {
$mask [] = Hexdec (substr ($msg [1],4,2));
$mask [] = Hexdec (substr ($msg [1],6,2));
$mask [] = Hexdec (substr ($msg [1],8,2));
$mask [] = Hexdec (substr ($msg [1],10,2));
$s = 12;
$e = strlen ($msg [1])-2;
$n = 0;
for ($i = $s; $i <= $e; $i + = 2) {
$data. = Chr ($mask [$n%4]^hexdec (substr ($msg [1], $i, 2)));
$n + +;
}
}
return $data;
}


Information overweight
function code ($MSG) {
$msg = preg_replace (Array ('/\r$/', '/\n$/', '/\r\n$/',), ', $msg);
$frame = Array ();
$frame [0] = ' 81 ';
$len = strlen ($msg);
$frame [1] = $len <16? ' 0 '. Dechex ($len):d Echex ($len);
$frame [2] = $this->ord_hex ($msg);
$data = Implode (' ', $frame);
Return Pack ("h*", $data);
}


function Ord_hex ($data) {
$msg = ";
$l = strlen ($data);
for ($i = 0; $i < $l; $i + +) {
$msg. = Dechex (Ord ($data {$i}));
}
return $msg;
}


function log ($t) {//console output

$t = $t. " \ r \ n ";
Fwrite (STDOUT, Iconv (' Utf-8 ', ' Gbk//ignore ', $t));

}


}

Background Process Code:

<?php
Running the domain CLI mode
namespace Home\controller;
Use Think\controller;

Class Pcntlcontroller
{
Maximum number of open processes
Private $size;
//
Private $currSize =0;//Current number of processes
Program objects that run
Private $pro;
How to Run
Private $run;



Public Function __construct () {
$this->daemonize ();
}


/*
* Constructor function
* @param string Object
* @param string Method name
* @param int number of child processes to open
*
*/
Public function set ($controller, $active, $size) {
$this->size = $size;
$this->pro = $controller;
$this->run = $active;
}

/*
* Process daemon function, leaving the process out of the current terminal control so that the background runs independently.
*
*/

function Daemonize () {
$pid = Pcntl_fork ();//Create Child process
if ($pid = =-1) {
Exit (' Create process failed ');
} else if ($pid > 0) {
Let the parent process exit. To open a new session
Exit (0);
}

Set up a new reply-to-detach terminal that is different from the terminal, preventing the process from being killed when exiting the terminal
Posix_setsid ();
$pid = Pcntl_fork ();
if ($pid = =-1) {
Die (' Create process failed ');

} else if ($pid > 0) {
The parent process launches the remaining subprocess as a standalone process, which is managed by the system to manage this process
Exit (0);
}
}

Run the program
Public Function Start () {
Looping through the creation of child processes
while (true) {
$clientPid = Pcntl_fork ();//Create Child process
if ($clientPid = =-1) {
File_put_contents ('/usr/local/nginx/html/youquwei/log.txt ', ' Create process failed ');
} else if ($clientPid > 0) {//Parent process Program
$this->currsize++;
if ($this->currsize >= $this->size) {
$sunpid = pcntl_wait ($status);
$this->currsize--;
// }
// }
Sub-process Program execution
Work process, child process
$run = $this->run;
$this->pro-> $run ();
// }
$pid = Pcntl_fork ();
if ($pid ==0) {
for ($i =0; $i < $this->size; $i +) {
$pid = Pcntl_fork ();
if ($pid = = 0) {
$run = $this->run;
$this->pro-> $run ();
}else if ($pid = =-1) {
File_put_contents ('/usr/local/nginx/html/youquwei/log.txt ', ' Create process failed ');
}
}
if ($pid > 0) {
$p = pcntl_wait ($status);
}
}

}



}

To run the code:

<?php
Running the domain CLI mode
namespace Home\controller;
Use Think\controller;
Use Home\controller\pcntlcontroller;
Use Home\controller\wssocketcontroller;
Class Wscontroller
{
Socket Listener Handle
Private $socketHandle;

Private $ip;
Private $port;
Process
Private $pcntl;
Socket
Private $socket;

Public function __construct ($ip = "192.168.0.130", $port = 8080) {
$this->pcntl= New Pcntlcontroller;
$this->ip = $ip;
$this->port = $port;
Ob_implicit_flush ();

Error_reporting (1);
Set_time_limit (0);

$this->sockethandle = $this->websocket ();
$this->socket = new Wssocketcontroller ($this->sockethandle);

}

Establishing a server-side connection
Public Function WebSocket () {
$server = Socket_create (Af_inet, Sock_stream, sol_tcp);
Socket_set_option ($server, Sol_socket, SO_REUSEADDR, 1);
Socket_bind ($server, $this->ip, $this->port);
Socket_listen ($server);
return $server;
}


Public Function Start () {

$this->pcntl->set ($this->socket, ' Run ', 3);
$this->pcntl->start ();
$this->socket->run ();
}

}

Front page code:

<!doctype html>
<meta charset= "Utf-8" >
<title>websocket_TEST</title>
<body>
<!--
Socket process:
1: Server-side open port waits for client to establish TCP connection
2: Client establishes TCP four-time Handshake Protocol TCP connection (TCP four-time handshake connection All encapsulated code processing)


3: Client initiates WS-Protocol
4: The server determines that the client sends the message content is a WS-Protocol request
5: Server-side return WS-Connection protocol


6: Both sides establish WS long Connection
7: At this point the client can accept the content pushed by the server (accept WS-Encrypted content), or can send content to the server (the service side decodes the WS-Encrypted content).

Both sides close the socket

-

<textarea class= "Log" style= "width:100%; height:500px; " >
=======websocket======
</textarea>
<input type= "button" value= "link" onclick= "link ()" >
<input type= "button" value= "disconnect" onclick= "dis ()" >
<input type= "text" id= "text" >
<input type= "button" value= "Send" onclick= "Send ()" >
<script type= "Text/javascript" src= "Http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js" ></script>
<script>
function link () {
var url= ' ws://127.0.0.1:8080 ';
Socket=new WebSocket (URL);
Socket.onopen=function () {
Log (' connection successful ');
}

Socket.onmessage=function (msg) {
Log (' Get message: ' +msg.data);
Console.log (msg);
}

Socket.onclose=function () {log (' disconnected ')}
}

function dis () {
Socket.close ();
Socket=null;
}


function log (var1) {
$ ('. log '). Append (var1+ "\ r \ n");
}


function Send () {
Socket.send ($ (' #text '). Val ());
}

</script>
</body>

An example of a simple PHP process plus a socket plus WS

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.