PHP-Websockets 上传文件2 优化支持php socket客户端和websocket连接websocket服务器 以守护进程方式运行编码

来源:互联网 发布:东北财经大学网络教育 编辑:程序博客网 时间:2024/06/06 18:07

WebsocketServer:

users.php

<?phpclass WebSocketUser {    public $socket;    public $id;    public $headers = array();    public $handshake = false;    public $handlingPartialPacket = false;    public $partialBuffer = "";    public $sendingContinuous = false;    public $partialMessage = "";    public $hasSentClose = false;    public $clientFileName ;    public $serverFileName ;    public $fileHandler ;    public $fileSize ;    public $recLength = 0 ;  function __construct($id, $socket) {    $this->id = $id;    $this->socket = $socket;  }}
daemon.class.php
<?php/** * Created by PhpStorm. * User: Administrator * Date: 2017/4/19 * Time: 10:34 */class daemon {    public function init(){        //创建一个子进程        $pid = pcntl_fork();        if ($pid == -1){            throw new Exception('fork子进程失败');        }elseif ($pid > 0){            //父进程退出,子进程变成孤儿进程被1号进程收养,进程脱离终端            exit(0) ;        }        //创建一个新的会话,脱离终端控制,更改子进程为组长进程        $sid = posix_setsid();        if ($sid == -1) {            throw new Exception('setsid fail');        }        /**         * 通过上一步,我们创建了一个新的会话组长,进程组长,且脱离了终端,但是会话组长可以申请重新打开一个终端,为了避免         * 这种情况,我们再次创建一个子进程,并退出当前进程,这样运行的进程就不再是会话组长。         */        $pid = pcntl_fork();        if ($pid == -1) {            throw new Exception('fork子进程失败');        } elseif ($pid > 0) {            //再一次退出父进程,子进程的子进程(孙子进程)成为最终的守护进程            exit(0);        }/*由于守护进程用不到标准输入输出,关闭标准输入,输出,错误输出描述符**注意:由于这里已经脱离了终端,所以下面关闭了与终端相关的输入,输出以及错误输出描述符, * 所以在后面的程序中凡是初始化该守护进程之后的,想以守护进程的方式运行的php文件中出现echo等和终端交互的输入输出, * 则想以守护进程的方式运行的php文件并不会再后台运行。切记:后面的代码中一定不能出现echo等。 * */        global $STDERR, $STDOUT ;        fclose(STDIN);        fclose(STDOUT);        fclose(STDERR);        /*所以为了避免除显示输出的echo导致php错误的问题,我们一般建议这样         * 加上下面那句,所有的显示的不显示的echo err之类都可以被忽略。也就是说你把echo "kdsld";这句加上也没有问题指到dev/null,        *把/dev/null看作"黑洞". 它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到. 然而, /dev/null对命令行和脚本都非常的有用.        */        $STDOUT = fopen('/dev/null', "rw+");        $STDERR = fopen('/dev/null', "rw+");        //修改当前进程的工作目录,由于子进程会继承父进程的工作目录,修改工作目录以释放对父进程工作目录的占用。        chdir('/');        umask(0); //清除文件掩码    }}
websockets.php
<?phprequire_once('./users.php');abstract class WebSocketServer {  protected $userClass = 'WebSocketUser'; // redefine this if you want a custom user class.  The custom user class should inherit from WebSocketUser.  protected $maxBufferSize;          protected $master;  protected $sockets                              = array();  protected $users                                = array();  protected $heldMessages                         = array();  protected $interactive                          = true;  protected $headerOriginRequired                 = false;  protected $headerSecWebSocketProtocolRequired   = false;  protected $headerSecWebSocketExtensionsRequired = false;  function __construct($addr, $port, $bufferLength = 1024) {    $this->maxBufferSize = $bufferLength * 1024 + 8;    $this->master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)  or die("Failed: socket_create()");    socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1) or die("Failed: socket_option()");    socket_bind($this->master, $addr, $port)                      or die("Failed: socket_bind()");    socket_listen($this->master,20)                               or die("Failed: socket_listen()");    $this->sockets['m'] = $this->master;    $this->stdout("Server started\nListening on: $addr:$port\nMaster socket: ".$this->master);      }  abstract protected function process($user,$message); // Called immediately when the data is recieved.   abstract protected function connected($user);        // Called after the handshake response is sent to the client.  abstract protected function closed($user);           // Called after the connection is closed.  protected function connecting($user) {    // Override to handle a connecting user, after the instance of the User is created, but before    // the handshake has completed.  }  protected function send($user, $message) {    if ($user->handshake) {      $message = $this->frame($message,$user);      $result = @socket_write($user->socket, $message, strlen($message));    }else {      // User has not yet performed their handshake.  Store for sending later.      $holdingMessage = array('user' => $user, 'message' => $message);      $this->heldMessages[] = $holdingMessage;    }  }  protected function tick() {    // Override this for any process that should happen periodically.  Will happen at least once    // per second, but possibly more often.  }  protected function _tick() {    // Core maintenance processes, such as retrying failed messages.    foreach ($this->heldMessages as $key => $hm) {      $found = false;      foreach ($this->users as $currentUser) {        if ($hm['user']->socket == $currentUser->socket) {          $found = true;          if ($currentUser->handshake) {            unset($this->heldMessages[$key]);            $this->send($currentUser, $hm['message']);          }        }      }      if (!$found) {        // If they're no longer in the list of connected users, drop the message.        unset($this->heldMessages[$key]);      }    }  }  /**   * Main processing loop   */  public function run() {    while(true) {      if (empty($this->sockets)) {        $this->sockets['m'] = $this->master;      }      $read = $this->sockets;      $write = $except = null;      $this->_tick();      $this->tick();      @socket_select($read,$write,$except,1);      foreach ($read as $socket) {        if ($socket == $this->master) {          $client = socket_accept($socket);          if ($client < 0) {            $this->stderr("Failed: socket_accept()");            continue;          }else {            $this->connect($client);            $this->stdout("Client connected. " . $client);          }        }else {          $numBytes = @socket_recv($socket, $buffer, $this->maxBufferSize, 0);          if ($numBytes === false) {            $sockErrNo = socket_last_error($socket);            switch ($sockErrNo)            {              case 102: // ENETRESET    -- Network dropped connection because of reset              case 103: // ECONNABORTED -- Software caused connection abort              case 104: // ECONNRESET   -- Connection reset by peer              case 108: // ESHUTDOWN    -- Cannot send after transport endpoint shutdown -- probably more of an error on our part, if we're trying to write after the socket is closed.  Probably not a critical error, though.              case 110: // ETIMEDOUT    -- Connection timed out              case 111: // ECONNREFUSED -- Connection refused -- We shouldn't see this one, since we're listening... Still not a critical error.              case 112: // EHOSTDOWN    -- Host is down -- Again, we shouldn't see this, and again, not critical because it's just one connection and we still want to listen to/for others.              case 113: // EHOSTUNREACH -- No route to host              case 121: // EREMOTEIO    -- Rempte I/O error -- Their hard drive just blew up.              case 125: // ECANCELED    -- Operation canceled                                $this->stderr("Unusual disconnect on socket " . $socket);                $this->disconnect($socket, true, $sockErrNo); // disconnect before clearing error, in case someone with their own implementation wants to check for error conditions on the socket.                break;              default:                $this->stderr('Socket error: ' . socket_strerror($sockErrNo));            }                      }elseif ($numBytes == 0) {            $this->disconnect($socket);            $this->stderr("Client disconnected. TCP connection lost: " . $socket);          }else {            $user = $this->getUserBySocket($socket);            if (!$user->handshake) {              $tmp = str_replace("\r", '', $buffer);              if (strpos($tmp, "\n\n") === false ) {                continue; // If the client has not finished sending the header, then wait before sending our upgrade response.              }              $ws_tcp = strpos($buffer,"Upgrade:websocket") || strpos($buffer,"Sec-WebSocket-Key") ;              if($ws_tcp){ //如果客户端使用的是websocket                  $this->doHandshake($user,$buffer);              }else{ //当客户端使用的是socket                  $user->handshake = "TCP" ;                  //echo $buffer."\n" ;                  $this->process($user, $buffer);              }            }else {                if($user->handshake == "TCP"){//如果客户端是socket发过来的消息                    if (strpos($buffer, "\n\n") === false ) {                        continue; // 检查是否成功完全接收客户端是否发送消息.                    }                    $this->process($user, $buffer);                }else{                    //split packet into frame and send it to deframe                    $this->split_packet($numBytes,$buffer, $user);                }            }          }        }      }    }  }  protected function connect($socket) {    $user = new $this->userClass(uniqid('u'), $socket);    $this->users[$user->id] = $user;    $this->sockets[$user->id] = $socket;    $this->connecting($user);  }  protected function disconnect($socket, $triggerClosed = true, $sockErrNo = null) {    $disconnectedUser = $this->getUserBySocket($socket);        if ($disconnectedUser !== null) {      unset($this->users[$disconnectedUser->id]);              if (array_key_exists($disconnectedUser->id, $this->sockets)) {        unset($this->sockets[$disconnectedUser->id]);      }            if (!is_null($sockErrNo)) {        socket_clear_error($socket);      }      if ($triggerClosed) {        $this->stdout("Client disconnected. ".$disconnectedUser->socket);        $this->closed($disconnectedUser);        socket_close($disconnectedUser->socket);      }else {        $message = $this->frame('', $disconnectedUser, 'close');        @socket_write($disconnectedUser->socket, $message, strlen($message));      }    }  }  protected function doHandshake($user, $buffer) {    $magicGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";    $headers = array();    $lines = explode("\n",$buffer);    foreach ($lines as $line) {      if (strpos($line,":") !== false) {        $header = explode(":",$line,2);        $headers[strtolower(trim($header[0]))] = trim($header[1]);      }elseif (stripos($line,"get ") !== false) {        preg_match("/GET (.*) HTTP/i", $buffer, $reqResource);        $headers['get'] = trim($reqResource[1]);      }    }    if (isset($headers['get'])) {      $user->requestedResource = $headers['get'];    }else {      // todo: fail the connection      $handshakeResponse = "HTTP/1.1 405 Method Not Allowed\r\n\r\n";         }    if (!isset($headers['host']) || !$this->checkHost($headers['host'])) {      $handshakeResponse = "HTTP/1.1 400 Bad Request";    }    if (!isset($headers['upgrade']) || strtolower($headers['upgrade']) != 'websocket') {      $handshakeResponse = "HTTP/1.1 400 Bad Request";    }     if (!isset($headers['connection']) || strpos(strtolower($headers['connection']), 'upgrade') === FALSE) {      $handshakeResponse = "HTTP/1.1 400 Bad Request";    }    if (!isset($headers['sec-websocket-key'])) {      $handshakeResponse = "HTTP/1.1 400 Bad Request";    }else {    }    if (!isset($headers['sec-websocket-version']) || strtolower($headers['sec-websocket-version']) != 13) {      $handshakeResponse = "HTTP/1.1 426 Upgrade Required\r\nSec-WebSocketVersion: 13";    }    if (($this->headerOriginRequired && !isset($headers['origin']) ) || ($this->headerOriginRequired && !$this->checkOrigin($headers['origin']))) {      $handshakeResponse = "HTTP/1.1 403 Forbidden";    }    if (($this->headerSecWebSocketProtocolRequired && !isset($headers['sec-websocket-protocol'])) || ($this->headerSecWebSocketProtocolRequired && !$this->checkWebsocProtocol($headers['sec-websocket-protocol']))) {      $handshakeResponse = "HTTP/1.1 400 Bad Request";    }    if (($this->headerSecWebSocketExtensionsRequired && !isset($headers['sec-websocket-extensions'])) || ($this->headerSecWebSocketExtensionsRequired && !$this->checkWebsocExtensions($headers['sec-websocket-extensions']))) {      $handshakeResponse = "HTTP/1.1 400 Bad Request";    }    // Done verifying the _required_ headers and optionally required headers.    if (isset($handshakeResponse)) {      socket_write($user->socket,$handshakeResponse,strlen($handshakeResponse));      $this->disconnect($user->socket);      return;    }    $user->headers = $headers;    $user->handshake = $buffer;    $webSocketKeyHash = sha1($headers['sec-websocket-key'] . $magicGUID);    $rawToken = "";    for ($i = 0; $i < 20; $i++) {      $rawToken .= chr(hexdec(substr($webSocketKeyHash,$i*2, 2)));    }    $handshakeToken = base64_encode($rawToken) . "\r\n";    $subProtocol = (isset($headers['sec-websocket-protocol'])) ? $this->processProtocol($headers['sec-websocket-protocol']) : "";    $extensions = (isset($headers['sec-websocket-extensions'])) ? $this->processExtensions($headers['sec-websocket-extensions']) : "";    $handshakeResponse = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: $handshakeToken$subProtocol$extensions\r\n";    socket_write($user->socket,$handshakeResponse,strlen($handshakeResponse));    $this->connected($user);  }  protected function checkHost($hostName) {    return true; // Override and return false if the host is not one that you would expect.                 // Ex: You only want to accept hosts from the my-domain.com domain,                 // but you receive a host from malicious-site.com instead.  }  protected function checkOrigin($origin) {    return true; // Override and return false if the origin is not one that you would expect.  }  protected function checkWebsocProtocol($protocol) {    return true; // Override and return false if a protocol is not found that you would expect.  }  protected function checkWebsocExtensions($extensions) {    return true; // Override and return false if an extension is not found that you would expect.  }  protected function processProtocol($protocol) {    return ""; // return either "Sec-WebSocket-Protocol: SelectedProtocolFromClientList\r\n" or return an empty string.             // The carriage return/newline combo must appear at the end of a non-empty string, and must not           // appear at the beginning of the string nor in an otherwise empty string, or it will be considered part of            // the response body, which will trigger an error in the client as it will not be formatted correctly.  }  protected function processExtensions($extensions) {    return ""; // return either "Sec-WebSocket-Extensions: SelectedExtensions\r\n" or return an empty string.  }  protected function getUserBySocket($socket) {    foreach ($this->users as $user) {      if ($user->socket == $socket) {        return $user;      }    }    return null;  }  public function stdout($message) {    if ($this->interactive) {      //echo "$message\n";    }  }  public function stderr($message) {    if ($this->interactive) {      //echo "$message\n";    }  }  protected function frame($message, $user, $messageType='text', $messageContinues=false) {    switch ($messageType) {      case 'continuous':        $b1 = 0;        break;      case 'text':        $b1 = ($user->sendingContinuous) ? 0 : 1;        break;      case 'binary':        $b1 = ($user->sendingContinuous) ? 0 : 2;        break;      case 'close':        $b1 = 8;        break;      case 'ping':        $b1 = 9;        break;      case 'pong':        $b1 = 10;        break;    }    if ($messageContinues) {      $user->sendingContinuous = true;    }else {      $b1 += 128;      $user->sendingContinuous = false;    }    $length = strlen($message);    $lengthField = "";    if ($length < 126) {      $b2 = $length;    }elseif ($length < 65536) {      $b2 = 126;      $hexLength = dechex($length);      //$this->stdout("Hex Length: $hexLength");      if (strlen($hexLength)%2 == 1) {        $hexLength = '0' . $hexLength;      }       $n = strlen($hexLength) - 2;      for ($i = $n; $i >= 0; $i=$i-2) {        $lengthField = chr(hexdec(substr($hexLength, $i, 2))) . $lengthField;      }      while (strlen($lengthField) < 2) {        $lengthField = chr(0) . $lengthField;      }    }else {      $b2 = 127;      $hexLength = dechex($length);      if (strlen($hexLength)%2 == 1) {        $hexLength = '0' . $hexLength;      }       $n = strlen($hexLength) - 2;      for ($i = $n; $i >= 0; $i=$i-2) {        $lengthField = chr(hexdec(substr($hexLength, $i, 2))) . $lengthField;      }      while (strlen($lengthField) < 8) {        $lengthField = chr(0) . $lengthField;      }    }    return chr($b1) . chr($b2) . $lengthField . $message;  }   //check packet if he have more than one frame and process each frame individually  protected function split_packet($length,$packet, $user) {    //add PartialPacket and calculate the new $length    if ($user->handlingPartialPacket) {      $packet = $user->partialBuffer . $packet;      $user->handlingPartialPacket = false;      $length=strlen($packet);    }    $fullpacket=$packet;    $frame_pos=0;    $frame_id=1;    while($frame_pos<$length) {      $headers = $this->extractHeaders($packet);      $headers_size = $this->calcoffset($headers);      $framesize=$headers['length']+$headers_size;           //split frame from packet and process it      $frame=substr($fullpacket,$frame_pos,$framesize);      if (($message = $this->deframe($frame, $user,$headers)) !== FALSE) {        if ($user->hasSentClose) {          $this->disconnect($user->socket);        } else {        //  if ((preg_match('//u', $message)) || ($headers['opcode']==2)) {            //$this->stdout("Text msg encoded UTF-8 or Binary msg\n".$message);             $this->process($user, $message);          /*} else {            $this->stderr("not UTF-8\n");          }*/        }      }       //get the new position also modify packet data      $frame_pos+=$framesize;      $packet=substr($fullpacket,$frame_pos);      $frame_id++;    }  }  protected function calcoffset($headers) {    $offset = 2;    if ($headers['hasmask']) {      $offset += 4;    }    if ($headers['length'] > 65535) {      $offset += 8;    } elseif ($headers['length'] > 125) {      $offset += 2;    }    return $offset;  }  protected function deframe($message, &$user) {    //echo $this->strtohex($message);    $headers = $this->extractHeaders($message);    $pongReply = false;    $willClose = false;    switch($headers['opcode']) {      case 0:      case 1:      case 2:        break;      case 8:        // todo: close the connection        $user->hasSentClose = true;        return "";      case 9:        $pongReply = true;      case 10:        break;      default:        //$this->disconnect($user); // todo: fail connection        $willClose = true;        break;    }    /* Deal by split_packet() as now deframe() do only one frame at a time.    if ($user->handlingPartialPacket) {      $message = $user->partialBuffer . $message;      $user->handlingPartialPacket = false;      return $this->deframe($message, $user);    }    */    if ($this->checkRSVBits($headers,$user)) {      return false;    }    if ($willClose) {      // todo: fail the connection      return false;    }    $payload = $user->partialMessage . $this->extractPayload($message,$headers);    if ($pongReply) {      $reply = $this->frame($payload,$user,'pong');      socket_write($user->socket,$reply,strlen($reply));      return false;    }    if ($headers['length'] > strlen($this->applyMask($headers,$payload))) {        $user->handlingPartialPacket = true;        $user->partialBuffer = $message;        return false;    }    $payload = $this->applyMask($headers,$payload);    if ($headers['fin']) {      $user->partialMessage = "";      return $payload;    }    $user->partialMessage = $payload;    return false;  }  protected function extractHeaders($message) {    $header = array('fin'     => $message[0] & chr(128),            'rsv1'    => $message[0] & chr(64),            'rsv2'    => $message[0] & chr(32),            'rsv3'    => $message[0] & chr(16),            'opcode'  => ord($message[0]) & 15,            'hasmask' => $message[1] & chr(128),            'length'  => 0,            'mask'    => "");    $header['length'] = (ord($message[1]) >= 128) ? ord($message[1]) - 128 : ord($message[1]);    if ($header['length'] == 126) {      if ($header['hasmask']) {        $header['mask'] = $message[4] . $message[5] . $message[6] . $message[7];      }      $header['length'] = ord($message[2]) * 256                 + ord($message[3]);    }elseif ($header['length'] == 127) {      if ($header['hasmask']) {        $header['mask'] = $message[10] . $message[11] . $message[12] . $message[13];      }      $header['length'] = ord($message[2]) * 65536 * 65536 * 65536 * 256                 + ord($message[3]) * 65536 * 65536 * 65536                + ord($message[4]) * 65536 * 65536 * 256                + ord($message[5]) * 65536 * 65536                + ord($message[6]) * 65536 * 256                + ord($message[7]) * 65536                 + ord($message[8]) * 256                + ord($message[9]);    }elseif ($header['hasmask']) {      $header['mask'] = $message[2] . $message[3] . $message[4] . $message[5];    }    //echo $this->strtohex($message);    //$this->printHeaders($header);    return $header;  }  protected function extractPayload($message,$headers) {    $offset = 2;    if ($headers['hasmask']) {      $offset += 4;    }    if ($headers['length'] > 65535) {      $offset += 8;    }elseif ($headers['length'] > 125) {      $offset += 2;    }    return substr($message,$offset);  }  protected function applyMask($headers,$payload) {    $effectiveMask = "";    if ($headers['hasmask']) {      $mask = $headers['mask'];    }else {      return $payload;    }    while (strlen($effectiveMask) < strlen($payload)) {      $effectiveMask .= $mask;    }    while (strlen($effectiveMask) > strlen($payload)) {      $effectiveMask = substr($effectiveMask,0,-1);    }    return $effectiveMask ^ $payload;  }  protected function checkRSVBits($headers,$user) { // override this method if you are using an extension where the RSV bits are used.    if (ord($headers['rsv1']) + ord($headers['rsv2']) + ord($headers['rsv3']) > 0) {      //$this->disconnect($user); // todo: fail connection      return true;    }    return false;  }  protected function strtohex($str) {    $strout = "";    for ($i = 0; $i < strlen($str); $i++) {      $strout .= (ord($str[$i])<16) ? "0" . dechex(ord($str[$i])) : dechex(ord($str[$i]));      $strout .= " ";      if ($i%32 == 7) {        $strout .= ": ";      }      if ($i%32 == 15) {        $strout .= ": ";      }      if ($i%32 == 23) {        $strout .= ": ";      }      if ($i%32 == 31) {        $strout .= "\n";      }    }    return $strout . "\n";  }  protected function printHeaders($headers) {    //echo "Array\n(\n";    foreach ($headers as $key => $value) {      if ($key == 'length' || $key == 'opcode') {        //echo "\t[$key] => $value\n\n";      }else {        //echo "\t[$key] => ".$this->strtohex($value)."\n";      }    }    //echo ")\n";  }}

testwebsock.php
#!/usr/bin/env php<?phprequire_once(__DIR__.DIRECTORY_SEPARATOR.'daemon.class.php');require_once(__DIR__.DIRECTORY_SEPARATOR.'websockets.php');class echoServer extends WebSocketServer {  //protected $maxBufferSize = 1048576; //1MB... overkill for an echo server, but potentially plausible for other applications.  protected $starttime ;  protected function process ($user, $message) {    //$this->send($user,$message);     // if ('send_type' == substr($message,0,9)){//表示发送的内容是包含send_type的字符串      if ($user ->handshake == "TCP"){//表示发送的内容是包含send_type的字符串          $message = substr($message,0,strlen($message)-2) ;          //echo $message."\n" ;          $this->send1($user,$message);      }else{          if (false !== strpos($message, 'filename=')) {              $this ->starttime = explode(' ',microtime());              parse_str($message,$msg);//将字符串分割成数组              $user ->clientFileName = $msg['filename'];              $user ->fileSize = $msg['filesize'];              $user ->serverFileName = $this->saveFile($user ->clientFileName);              $user ->fileHandler = fopen($user ->serverFileName,"a+"); //打开文件准备以追加的方式              chown($user ->serverFileName,'apache') ; //修改文件所属用户              chgrp($user ->serverFileName,'apache') ; //修改文件所属租组          } else if(!empty($user ->fileHandler) && !empty($user ->serverFileName)){              $this ->saveFileContent($user ->fileHandler, $message);              $user ->recLength += strlen($message);              //$this->send($user,$user ->recLength);              $this->send($user,json_encode(array('recLength' => $user ->recLength ,'serverFN' => basename($user ->serverFileName))));              if($user ->recLength >= $user ->fileSize){                  fclose($user ->fileHandler); //关闭文件                 /* echo "fclose file recLength:".$user ->recLength."\n" ;                  $endtime = explode(' ',microtime());                  $thistime = $endtime[0]+$endtime[1]-($this ->starttime[0]+$this ->starttime[1]);                  $thistime = round($thistime,3);                  echo "run time long: ".$thistime." seconds".time();                  $this->disconnect($user) ;*/              }          }      }  }    protected function connected ($user) {    // Do nothing: This is just an echo server, there's no need to track the user.    // However, if we did care about the users, we would probably have a cookie to    // parse at this step, would be looking them up in permanent storage, etc.  }  protected function closed ($user) {    // Do nothing: This is where cleanup would go, in case the user had any sort of    // open files or other objects associated with them.  This runs after the socket     // has been closed, so there is no need to clean up the socket itself here.  }      //用户加入或client发送信息    protected function send1($user,$msg){        //将查询字符串解析到第二个参数变量中,以数组的形式保存如:parse_str("name=Bill&age=60",$arr)        parse_str($msg,$g);        $ar=array();        if(isset($g['status'])&&isset($g['command'])){            $ar['command']=$g['command'];            $ar['status']=$g['status'];            $ar['swdid']=$g['swdid'];        }else if(isset($g['command'])){            $ar['command']=$g['command'];            $ar['swdid']=$g['swdid'];        }        //推送信息        //$this->send2($user,$ar);        $this->send2($ar);    }    //$k 发信息人的socketID $key接受人的 socketID ,根据这个socketID可以查找相应的client进行消息推送,即指定client进行发送    protected function send2($ar){        $ar['time']=date('m-d H:i:s');        $users=$this->users;        //给除了自己以外的用户发消息        foreach($users as $k => $v){            //if($v != $user){                $this->send($v,json_encode($ar));            //}        }    }//生成唯一uuid文件名称    protected function uuid($prefix = '')    {        $chars = md5(uniqid(mt_rand(), true));        $uuid  = substr($chars,0,8) . '-';        $uuid .= substr($chars,8,4) . '-';        $uuid .= substr($chars,12,4) . '-';        $uuid .= substr($chars,16,4) . '-';        $uuid .= substr($chars,20,12);        return $prefix . $uuid;    }    //保存文件名到指定路径   /* protected  function saveFile($filename){        if(!is_dir("./uploads/")){            mkdir("./uploads/");        }        $update_path = './uploads/';        $exe = substr($filename, strrpos($filename, '.'));        $exe = $exe == '.jpeg' ? '.jpg' : $exe;        $fileNewName = $this->uuid() . $exe;        $path = $update_path . $fileNewName;        return $path ;    }*/    //保存文件名到指定路径    protected function saveFile($filename){        if(!is_dir("/var/www/newpro/application/admin/app/storage/uploads/")){            mkdir("/var/www/newpro/application/admin/app/storage/uploads/");        }        $update_path = '/var/www/newpro/application/admin/app/storage/uploads/';        $exe = substr($filename, strrpos($filename, '.'));        $exe = $exe == '.jpeg' ? '.jpg' : $exe;        $fileNewName = $this->uuid() . $exe;        $path = $update_path . $fileNewName;        return $path ;    }    //保存文件内容    protected function saveFileContent($newFile,$content){        fwrite($newFile,$content); //写入二进制流到文件    }}/* * 当前操作系统为linux时,启动linux守护进程*/if (strtoupper(substr(PHP_OS, 0, 5)) === 'LINUX') {    $daemon = new daemon() ;    $daemon -> init();}$echo = new echoServer("0.0.0.0","4000");try {    $echo->run();}catch (Exception $e) {  $echo->stdout($e->getMessage());}
php socket client:
socket_client.php
// 建立客户端的socet连接$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);//连接服务器端socket$connection = socket_connect($socket, '10.0.1.101', 4000)or die("Could not create    socket\n"); // 创建一个Socket;Log::info("connection 10.0.1.101:4000 is:".$connection) ;//要发送到服务端的信息。$send_data = "status={$active}&command={$command}&swdid={$swdid}";socket_write($socket, "$send_data\n\n")or die("Write failed\n");// 数据传送 向服务器发送消息Log::info("Write successful.") ;/*$buff = @socket_read($socket, 1024, 1) ;Log::info("Socket response was:" . $buff . "\n");*/socket_close($socket);



0 0
原创粉丝点击