2014-02-18 1 views
0

저는 파이썬 소켓에 대해 배우고 있으며 telnet xxx.xxx.xxx.xxx 8888을 사용하여 폴링 할 수있는 하나의 컴퓨터에 짧은 서버 소켓 프로그램을 작성했습니다. 통신은 정상적으로 작동하지만 클라이언트에서 보낸 data을 평가할 때 어떤 이유로 클라이언트가 평가 한 것처럼 보이지 않습니다.if 문을 사용하여 Python 소켓 데이터가 예기치 않게 작동합니다.

기분을 상하게하는 코드는 다음과 같습니다 : 나는 다음을 수행 클라이언트에서

data = conn.recv(1024) # receive data 
    conn.sendall(data)  # reply to confirm what data was received 
    if data == "green": 
      reply = 'GREEN ON' 
    elif data == "red": 
      reply = 'RED ON' 
    else: 
      reply = 'Command not recognized' 
    conn.sendall(reply) 

:

telnet 192.168.0.8 8888 
Trying 192.168.0.8... 
Connected to 192.168.0.8. 
Escape character is '^]'. 
Welcome to the server. Type something and hit enter  # server responds with connection confirmation 
green   #typed from client 
green   #server responds with the data it received 
Command not recognized  #<-- data is not evaluated correctly in if statement 

그래서 일어나고있는 것은 내가 Welcome to the server...가를 나타내는 응답 telnet를 사용하여 서버를 폴링입니다 성공적인 연결. 그런 다음 green을 입력하면 서버가받은 데이터로 응답합니다 (즉, green). 그런 다음 서버 프로그램의 if 문이 data을 올바르게 평가하지 못했다는 의미로 명령이 인식되지 않는다고 알려줍니다.

데이터가 실제로 누락 되었습니까? green\0과 같이 null로 끝나는 것처럼 if 블록에서 잘못된 평가가 발생합니까?

답변

2

지시 사항과 마찬가지로 뭔가를 입력하고 Enter를 누르는 것 같습니다.

따라서 'green\n'을 보내고 있습니다. 또는 'green\r\n' 일 수도 있습니다.

어쨌든 'green\n' != 'green''green\r\n' != 'green'입니다.

테스트하는 좋은 방법은 얻은 것을 인쇄하는 것입니다. 문자열의 repr을 인쇄하면 모든 제어 문자가 인용되고 모든 제어 문자가 이스케이프됩니다. 따라서 정확히 green 대신 정확히 'green\r\n'이 표시되고 빈 줄이 뒤 따르기 때문에 해석하기가 훨씬 쉽습니다. 예를 들어,

당신은 확인하여이 문제를 해결할 수있는 대신 datadata.rstrip()을 (이것은 또한 당신이 등을 가짜 \0 터미네이터를 배제 할 것입니다). 당신이 그렇게하면

그러나 프로그램이 실제로 작업, 그냥 (로컬 호스트에서 테스트 같은) 시간 특정 상황에서, 또는 의 대부분을 작동합니다 것입니다. 이것은 잡기 힘든 버그를 만드는 방법입니다. 마지막으로 찾으면 전체 앱을 다시 작성해야합니다.

recv

은 별도의 세 가지 send의에서 단일 send의 데이터, 또는 send에서 절반 데이터 또는 데이터를 얻을 수 있습니다. 'gre' 또는 'green\r\nbl'을 받으면 일치 항목을 만들지 않고 'green'이됩니다.

이 문제를 해결하려면 메시지를 어떤 식 으로든 구분하는 프로토콜을 디자인하고 recv을 반복하고 버퍼에 추가 한 다음 메시지를 분할해야합니다. 또는 프로토콜이 "모든 명령을 개행 문자로 종료합니다."(명령 내에 포함 된 개행 문자가없는 경우) socket.makefile을 사용할 수 있습니다.이 파일은 자동으로 파일과 유사한 객체를 제공하므로 사용자가 할 수 있습니다. 줄 단위로 반복하십시오 (또는 readline 등으로 호출하십시오.), 일반 파일로 할 수있는 것처럼. 보편적 인 개행 지원으로 열 수도 있습니다. 따라서 성가신 모순에 대해 걱정할 필요가 없습니다. \r\n\n.

자세한 내용은 Sockets are byte streams, not message streams을 참조하십시오.

+0

답장을 보내 주셔서 감사합니다. 나는 그 코드 행을'if data == "green \ n"'로 읽었지만 여전히 동일하게 변경했다. – nagyben

+0

@exantas : 실제로받은 것을보기 위해'print (repr (data)) '문장을 넣으십시오. 나는 그것이 '\ r \ n' 대'\ n' 문제 일 것이지만, 실제로 추측 할 이유가 없습니다. – abarnert

+0

당신이 맞았습니다. 실제로'녹색 \ r \ n'을 받았습니다. 그래도 좋은 팁입니다. 감사합니다! – nagyben

1

여기서 문제는 텔넷에서 개행 문자가 전송 된 것입니다. if 차단 전에 공백을 제거하십시오.

data = data.rstrip() 
관련 문제