设为首页 加入收藏

TOP

WebSocket 长连接 及超时问题解决(一)
2019-08-24 00:02:39 】 浏览:114
Tags:WebSocket 连接 超时 问题 解决
<?php
set_time_limit(0);
class SocketService { private $address = 'localhost'; private $port = 80; private $_sockets; public function __construct($address = '', $port='') { if(!empty($address)){ $this->address = $address; } if(!empty($port)) { $this->port = $port; } } public function service(){ //获取tcp协议号码。 $tcp = getprotobyname("SOL_TCP"); # 获取与协议名称关联的协议号 $sock = socket_create(AF_INET, SOCK_STREAM, $tcp); # 创建一个套接字(通讯节点) socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1); # 设置套接字选项 if($sock < 0) { throw new Exception("failed to create socket: ".socket_strerror($sock)."\n"); } socket_bind($sock, $this->address, $this->port); # 绑定 socket_listen($sock, $this->port); # 监听套接字上的连接 $this->_sockets = $sock; } public function run(){ $this->service(); $clients[] = $this->_sockets; # 数组存储 每个socket # 让服务器无限获取客户端传过来的信息 while (true){ $changes = $clients; $write = NULL; $except = NULL; socket_select($changes, $write, $except, NULL); foreach ($changes as $key => $_sock){ if($this->_sockets == $_sock){ # 判断是不是新接入的socket if(($newClient = socket_accept($_sock)) === false){ # 接受新的套接字上的连接 socket_accept的作用就是接受socket_bind()所绑定的主机发过来的套接流 die('failed to accept socket: '.socket_strerror($_sock)."\n"); # 返回描述套接字错误的字符串 } $line = trim(socket_read($newClient, 1024)); # 读取客户端传过来的资源,并转化为字符串 socket_read的作用就是读出socket_accept()的资源并把它转化为字符串 $this->handshaking($newClient, $line); //获取client ip socket_getpeername ($newClient, $ip); # 查询给定套接字的远程端,这可能导致主机/端口或UNIX文件系统路径,具体取决于其类型。 $clients[$ip] = $newClient; } else { # 读取该socket的信息,注意:第二个参数是引用传参即接收数据,第三个参数是接收数据的长度 $lenght = socket_recv($_sock, $buffer, 2048, 0); # 从已连接的socket接收数据 $lenght 接收到字符串长度 $msg = $this->message($buffer); # 接收到的信息 //在这里业务代码 fwrite(STDOUT, 'Please input a argument:'); $response = trim(fgets(STDIN)); // $this->send($_sock, $response); # 第二个参数是获取数据 要发送的信息 $this->send($_sock, '在线'); } } } } /** * 握手处理 * @param $newClient socket * @return int 接收到的信息 */ public function handshaking($newClient, $line){ $headers = array(); $lines = preg_split("/\r\n/", $line); # 通过一个正则表达式分隔字符串。 foreach($lines as $line) { $line = chop($line); # 移除字符串右端的空白字符或其他预定义字符 if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)) { $headers[$matches[1]] = $matches[2]; } } $secKey = $headers['Sec-WebSocket-Key']; $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'))); $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" . "WebSocket-Origin: $this->address\r\n" . "WebSocket-Location: ws://$this->address:$this->port/服务器地址\r\n". "Sec-WebSocket-Accept:$secAccept\r\n\r\n"; return socket_write($newClient, $upgrade, strlen($upgrade)); # socket_write的作用是向socket_create的套接流写入信息,或者向socket_accept的套接流写入信息 } /** * 解析接收数据 * @param $buffer * @return null|string */ public function message($buffer){ $len = $masks = $data = $decoded = null; $len = ord($buffer[1]) & 127; if ($len === 126) { $masks = substr($buff
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇ThinkPHP 中使用 IS_AJAX 判断原.. 下一篇MongoDB的导入与导出

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目