/** * @param $payload * @param string $type * @param bool $masked * @return bool|string */ private function hybi10Encode($payload, $type = 'text', $masked = true) { $frameHead = array(); $payloadLength = strlen($payload); switch ($type) { //文本内容 case 'text': // first byte indicates FIN, Text-Frame (10000001): $frameHead[0] = 129; break; //二进制内容 //二进制内容 case 'binary': case 'bin': // first byte indicates FIN, Text-Frame (10000010): $frameHead[0] = 130; break; case 'close': // first byte indicates FIN, Close Frame(10001000): $frameHead[0] = 136; break; case 'ping': // first byte indicates FIN, Ping frame (10001001): $frameHead[0] = 137; break; case 'pong': // first byte indicates FIN, Pong frame (10001010): $frameHead[0] = 138; break; } // set mask and payload length (using 1, 3 or 9 bytes) if ($payloadLength > 65535) { $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8); $frameHead[1] = $masked === true ? 255 : 127; for ($i = 0; $i < 8; $i++) { $frameHead[$i + 2] = bindec($payloadLengthBin[$i]); } // most significant bit MUST be 0 (close connection if frame too big) if ($frameHead[2] > 127) { $this->socket->close(); return false; } } elseif ($payloadLength > 125) { $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8); $frameHead[1] = $masked === true ? 254 : 126; $frameHead[2] = bindec($payloadLengthBin[0]); $frameHead[3] = bindec($payloadLengthBin[1]); } else { $frameHead[1] = $masked === true ? $payloadLength + 128 : $payloadLength; } // convert frame-head to string: foreach (array_keys($frameHead) as $i) { $frameHead[$i] = chr($frameHead[$i]); } // generate a random mask: $mask = array(); if ($masked === true) { for ($i = 0; $i < 4; $i++) { $mask[$i] = chr(rand(0, 255)); } $frameHead = array_merge($frameHead, $mask); } $frame = implode('', $frameHead); // append payload to frame: for ($i = 0; $i < $payloadLength; $i++) { $frame .= $masked ? $payload[$i] ^ $mask[$i % 4] : $payload[$i]; } return $frame; }