2013-05-11 4 views
0

파이썬을 통해 websocket 서버를 만드는 작업을하고 있습니다. (나는 파이썬에 좀 익숙합니다.) 상당한 진전을 이루었지만 데이터를 웹 브라우저로 보냅니다. 연결을 설정하고 브라우저에서 데이터를받을 수는 있지만 데이터를 다시 보낼 수는 없습니다. 브라우저는 그냥 무시합니다. 브라우저가 사양을 따르지 않는 패키지를 받으면 연결을 종료하지만 연결은 계속 활성화된다고 가정합니다.Websocket : 브라우저 dosn't는 파이썬 서버에서 데이터를 수신하는 것 같습니다

def encode_message(data): 
    frame = "\x81" 
    size = len(data) 
    if size * 8 <= 125: 
     frame += chr(size) 
    else: 
     raise Exception("Uh, oh. Strings larger than 125 bits are not supported") 

    return frame + data 

I가 sock.sendall(framed_data)를 사용하여 데이터를 전송하고있다 : 여기

은 I 프레임으로 데이터를 인코딩하기 위해 사용하고있는 방식이다. 무엇이 문제 일 수 있습니까? "yo"와 같은 메시지의 데이터는 10000001 00000010 01111001 01101111 (읽기 쉽도록 공백이 추가됨)이됩니다. 브라우저가 다음과 같은 메시지를 받아들이지 않는 이유는 무엇입니까? the specification에 요약 된 지침을 따르지 않습니까? 나는 버전 13이라고 생각되는 최신 websocket 버전을 지원하려고 노력 중이다. 파이썬 버전 2.7.3을 사용하고있다.

파이썬 websocket 라이브러리의 소스 코드를 살펴 보려고했지만, 모두 취약점이있는 것으로 표시된 웹 소켓 프로토콜의 비추천 버전을 구현하는 것 같습니다. 나는 또한 서버와 소켓 사이에 전송 패키지를 도청 와이어 샤크 다운로드

def send(data): 
    frame = encode_message(data) 
    print "Sending all..." 
    sock.sendall(frame) #Socket that handles all communications with client 
    print "Frame sent :)" 
    return 

: 여기

위의 함수를 호출하는 코드이다. 내 서버에서 보낸 패키지는 브라우저에서 허용 한 서버에서 보낸 패키지와 동일합니다. 나는 어떤 차이도 전혀 볼 수 없었다. (나는 16 진수 소스를 직접 보았습니다.)

+0

아무도이 문제를 해결하는 방법을 알고 있지 않습니까? – CoderOfHonor

+0

브라우저에서 어떤 콜백이 실행됩니까? 'onopen'은 핸드 쉐이크가 끝날 때 작동합니까? 'onerror' 또는'onclose'가 나중에 실행됩니까? 악수를 완료 한 후 연결을 유지하는 것을 기억합니까? 이 질문들 중 어느 것도 답을 찾는데 도움이되지 않는다면, 전체 서버 소스와 문제를 보여주는 간단한 클라이언트 코드를 게시 할 수 있습니까? – simonc

+0

'onopen'은 핸드 쉐이크가 끝날 때 실행됩니다. onclose는 웹 소켓이 서버에 의해 연결 해제 될 때까지 실행되지 않습니다. 오류가 발생하지 않기 때문에'onerror'는 호출되지 않습니다. 핸드 셰이크가 수행 된 후 서버는 클라이언트에서 메시지를 수신 할 수 있지만 그 반대는 작동하지 않습니다. – CoderOfHonor

답변

0

나는 마침내 문제를 알아 냈습니다! 불완전한 디버깅과 코드 작성에 몇 시간이 걸렸습니다. 서버와 클라이언트간에 앞뒤로 보낸 패키지를 면밀히 검토 한 결과 마침내 서버의 연결 업그레이드 응답에 문제가 있음을 알았습니다. 해시를 계산할 때마다 그 끝에 \n이 추가되었습니다. 그 결과 행 중 하나의 끝에 \n\r\n이 발생했습니다. 클라이언트는 전송이 끝나고 WebSocket 프로토콜을 사용하여 모든 내용을 분석했다고 해석했습니다. 그 뒤에 다른 줄이 있기 때문에 클라이언트와의 통신이 완전히 엉망이되었습니다. 나는 여전히 클라이언트에서 읽을 수 있지만 클라이언트에 쓰려고하면 데이터가 엉망이됩니다.

1

전송 된 메시지의 두 번째 바이트 (그리고 코드에서 길이 검사)가 잘못되었습니다. 메시지 길이는 비트가 아닌 바이트입니다. RFC6455 §5.2 가입일

(내 중점)

페이로드 길이 : 바이트 7 비트 7 + 16 비트 또는 7 + 64 비트

은 "페이로드 데이터"의 길이 : 0-125이면 페이로드 길이는 입니다.

브라우저에서 아무 것도 수신되지 않는 이유는 메시지가 16 바이트 본문이라고 주장하기 때문입니다. 브라우저는 보내는 추가 2 바이트를 읽은 다음 예상 한 다른 14 바이트를 기다리는 블록을 보내지 만 보내지 않습니다.

두 번째 바이트를 메시지의 바이트 수 (0x2 또는 00000010 바이너리)로 변경하면 모든 것이 작동합니다.

+0

나는 그것을 잡아 주셔서 감사 드리며, 귀하의 제안을 시도했지만, 여전히 메시지를받을 수있는 브라우저를 얻을 수 없습니다 ... – CoderOfHonor

+0

Daft 질문하지만 4 바이트를 보내고 있습니까? (32 바이트 문자열로 게시 한 이진 버전의 메시지가 아닙니다.)'encode_message'를 호출 한 코드를보고 프레임 데이터를 보내는 것이 흥미로울 것입니다. – simonc

+0

위 함수를 호출하는 코드를 추가했습니다. 보내고있는 실제 문자열은 다음과 같습니다. ' 좋아'. – CoderOfHonor

관련 문제