2013-03-31 3 views
0

나는 websocket을 처음 사용했습니다. PHP에서 간단한 websocket 구현을 만들었습니다. 내 서버가 클라이언트로부터 메시지를받을 수 있기 때문에 핸드 셰이 킹이 제대로 작동하고 연결이 확실히 켜져 있습니다.WebSocket : 클라이언트가 서버에 응답하지 않습니다

그러나 일단 클라이언트에 메시지를 보내려고하면 클라이언트는 전혀 응답하지 않습니다.

다음은 메시지를 마스크하여 클라이언트로 다시 보내는 코드입니다.

function myProcess($user,$buffer) 
{ 
//$buffer=unwrap($buffer); 
console("Request Caught."); 
console("Content Length: ".strlen($buffer)); 
console("Content: ".unmask($buffer)); 
console("First 8 bits: ".ord($buffer[0])); 
console("Opcode: ".opcode($buffer,true)); 
//console("Full Text: ".$buffer); 
//socket_write($user->socket,mask(unmask($buffer))); 
console("Masking: "); 
$tmp=unmask($buffer); 
console($tmp); 
$masked=mask($tmp); 
opcode($masked); 
for($i=0;$i<strlen($masked);$i++) 
{ 
    console($i.": ".ord($masked[$i])); 
} 
console("length: ".strlen($masked)); 
console("Sending Response: "); 
console(socket_write($user->socket,$masked,strlen($masked))); 
} 


function mask($text) 
{ 
    $first8bit=0x81; 
    $header; 
    console("mask: payload length:".strlen($text)); 
    if(strlen($text)<=125) 
    { 
     $header=pack("CC",$first8bit,strlen($text)); 
    } 
    else if(strlen($text)<65536) 
    { 
     $header=pack("CCS",$first8bit,126,strlen($text)); 
    } 
    else 
    { 
     $header=pack("CCN",$first8bit,127,strlen($text)); 
    } 
    return $header.$text; 
} 

클라이언트가 서버에 "hi"를 보내면 서버는 단순히 "hi"로 응답합니다. 그리고 wireshark를 가진 캡쳐 된 패킷은 81 02 68 69입니다. 프로토콜상의 것과 같이 전선의 비트가있는 것처럼 보입니다. 서버가 "hi from server"와 같이 더 긴 문자열을 보내려고하면 클라이언트 응답에 undefined가 표시됩니다.

아무도 도와 줄 수 있습니까? 고마워.

function dohandshake($user,$buffer){ 
    console("\nRequesting handshake..."); 
    console($buffer); 
    list($resource,$host,$origin,$strkey,$data) = getheaders($buffer); 
    console("Handshaking..."); 
    $upgrade="HTTP/1.1 101 Switching Protocols\r\n". 
        "Upgrade: websocket\r\n". 
        "Connection: Upgrade\r\n". 
        "Sec-WebSocket-Accept: ".calc_accept($strkey)."\r\n\r\n"; 
    socket_write($user->socket,$upgrade.chr(0),strlen($upgrade.chr(0))); 
    $user->handshake=true; 
    console($upgrade); 
    console("Done handshaking..."); 
    return true; 
} 

이 두 기능은 가져옵니다

function calc_accept($key) 
{ 
    $tmp=$key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 
    $tmp=sha1($tmp,true); 
    //console($tmp); 
    $tmp=base64_encode($tmp); 
    //console($tmp); 
    return $tmp; 
} 

이것은 악수 수행합니다

while(true){ 
    $changed = $sockets; 
    socket_select($changed,$write=NULL,$except=NULL,NULL); 
    foreach($changed as $socket){ 
    if($socket==$master){ 
     console("Master Socket Changed."); 
     $client=socket_accept($master); 
     if($client<0){ console("socket_accept() failed"); continue; } 
     else{ connect($client); } 
    } 
    else{ 
     console($socket." Socket Changed."); 
     $str=socket_read($socket,2048); 
     $user=getuserbysocket($socket); 
     if(strlen($str)==0) disconnect($socket); 
     else if(!$user->handshake){ dohandshake($user,$str); } 
     else 
     { 
      myProcess($socket,$str); 
     } 
     console("Comunication Ends Here."); 
    } 
    } 
} 

이 섹션 동의의 계산은 다음과 같습니다

서버의 코드 클라이언트 핸드 셰이크 및 소켓에 의한 사용자 객체 얻기 :

function getheaders($req){ 
    $r=$h=$o=null; 
    if(preg_match("/GET (.*) HTTP/" ,$req,$match)){ $r=$match[1]; } 
    if(preg_match("/Host: (.*)\r\n/" ,$req,$match)){ $h=$match[1]; } 
    if(preg_match("/Origin: (.*)\r\n/",$req,$match)){ $o=$match[1]; } 
    if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$req,$match)){ $key=$match[1]; } 
    if(preg_match("/\r\n(.*?)\$/",$req,$match)){ $data=$match[1]; } 
    return array($r,$h,$o,$key,$data); 
} 

function getuserbysocket($socket){ 
    global $users; 
    $found=null; 
    foreach($users as $user){ 
    if($user->socket==$socket){ $found=$user; break; } 
    } 
    return $found; 
} 
+0

올바른 소켓으로 클라이언트에 쓰고 있습니까? 클라이언트에게 메시지를 보내는 것은 소켓이 메시지를 수신하는 것과 별개입니다. – Stevko

+1

예, 새로 들어오는 소켓을 받아들이고 나중에 사용할 수 있도록 사용자 개체에 저장했습니다. 긴 문자열을 보낼 때 클라이언트에 오류가 발생하면 클라이언트가 바이트를 가져 오는 것으로 나타납니다. – Velissel

답변

0

pack의 형식 문자열은 126 - 65536 바이트 사이의 메시지에 잘못 표시됩니다. 당신은 내가 그것을 해결

"CCn" - unsigned short (16-bit) in "network" (big-endian) order

+0

나는 그것을 변경했지만, 도움이되지 않는다. "hi"의 길이는 2이다. 분명히 if 문> 125 && <= 65526에 도달하지 않을 것이다. – Velissel

+0

"hi"를 보내는 것이 효과가 있었지만 긴 메시지를 보내지는 못했습니다. "hi"전송도 실패합니까? – simonc

+0

내 상황은 "hi"를 클라이언트로 다시 보내면 클라이언트 측에서 응답을 보내지 않고 "hi from server"를 보내면 클라이언트 측에서 오류가 발생합니다. 정의되지 않았습니다. 더 구체적으로, 6 바이트보다 짧은 프레임을 전송하면 클라이언트는 응답하지 않지만 6 바이트보다 긴 모든 프레임을 전송하면 클라이언트는 오류 메시지를 표시합니다. – Velissel

0

"CCS" - unsigned short (always 16 bit, machine byte order)

을 변경 시도 할 수 있습니다. $ upgrade.chr (0), 업그레이드 ($를 나 strlen,

DELETE CHR (0) socket_write의 ($ 사용자 -> 소켓 : 이상한 문제에 어려움을 겪고 사람에게

,이 답이다. chr (0)))을 핸드 셰이크 함수에서 가져온다.

나는 그에게 영감을 주었기 때문에 simnoc의 대답을 올바른 것으로 표시 할 것입니다. 감사합니다

관련 문제