socket不好理解……个人理解,以PHP开发作为socket服务器,然后html5的websocket做为客户端,写一个聊天室,暂时只在网上找到聊天室,有空去找找一对一的。
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);// IPv4 网络协议,创建socket socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, TRUE); socket_bind($this->socket, $host, $port); socket_listen($this->socket, $max);
public function start() { $ii = 0; while(true) { $cycle = $this->accept; $cycle[] = $this->socket; socket_select($cycle, $write, $except, null);//监听各个客户端有没有信息进来,如果没有就卡在这里了。这个是非阻塞阻塞的获取信息,如果是socket_accept的话有客户端异常断开服务器就阻塞了,一般这里只选择出发生了信息交流的套接字。比如构造函数后会有$this->socket,如果没有任何客户端连接,就会停留在这里,比如一个客户端连接了,$this->socket得到连接请求,所以$this->socket会被选出,然后进入下面的循环,得到一个新的套接字资源,就是这个请求的客户端的套接字资源,下次循环的时候这个客户端套接字资源会进入下方的else foreach($cycle as $sock) { var_dump($sock); if($sock === $this->socket) {//判断是否为服务器的套接字,进入的话表示这个套接字未监听到资源信息 $client = socket_accept($this->socket);//接收套接字的资源信息,成功返回套接字的信息资源,失败为false $this->accept[] = $client; $key = array_keys($this->accept);//获取集合的key $this->isHand[$key] = false;//是否已经握手连接 } else { echo "other socket "; $length = socket_recv($sock, $buffer, 204800, 0);//从已连接的socket接收数据,数据保存在$buffer,返回接收到的字节数。 var_dump($length); $key = array_search($sock, $this->accept);//从$this->accept中搜索值$sock返回键 var_dump($key); if($length < 7) {//接受到的数据字节数 $this->close($sock); continue; } var_dump(!$this->isHand[$key]); var_dump($buffer); if(!$this->isHand[$key]) { $this->dohandshake($sock, $buffer, $key); var_dump("dd"); } else { // 先解码,再编码 $data = $this->decode($buffer); var_dump($data); $data = $this->encode($data); var_dump($data); // 判断断开连接(断开连接时数据长度小于10) if(strlen($data) > 10) { foreach($this->accept as $client) { socket_write($client, $data, strlen($data)); } } } } var_dump("ee"); } } }
public function dohandshake($sock, $data, $key) { if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $data, $match)) {//获取到Sec-WebSocket-Key $response = base64_encode(sha1($match[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));//258EAFA5-E914-47DA-95CA-C5AB0DC85B11 不知道为什么要这个字符串…… 有大神知道的吗? $upgrade = "HTTP/1.1 101 Switching Protocol\r\n" . "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" . "Sec-WebSocket-Accept: " . $response . "\r\n\r\n"; socket_write($sock, $upgrade, strlen($upgrade));//握手成功 $this->isHand[$key] = true; } }
/** * 解码过程 */ public 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; } /** * 编码过程 */ public function encode($buffer) { $length = strlen($buffer); if($length <= 125) { return "\x81".chr($length).$buffer; } else if($length <= 65535) { return "\x81".chr(126).pack("n", $length).$buffer; } else { return "\x81".char(127).pack("xxxxN", $length).$buffer; } }