WebsocketServer:
users.php
class 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
/** * 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
require_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 require_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);