使用if语句评估的Python套接字数据意外行为

时间:2014-02-18 23:09:34

标签: python sockets

我正在学习Python中的套接字,我在一台机器上编写了一个简短的服务器套接字程序,可以使用telnet xxx.xxx.xxx.xxx 8888进行轮询。通信工作正常,但出于某种原因,当我评估从客户端发送的data时,它似乎没有按照它应该进行评估。

违规代码如下:

    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

所以发生的事情是我使用telnet轮询服务器,Welcome to the server...响应green表示连接成功。然后我输入green,服务器响应它收到的数据(即if因此同一行两次)但后来告诉我命令无法识别,暗示data语句在服务器程序没有正确评估green\0

我是否遗漏了某些内容,例如数据实际上是空的终止,例如if导致{{1}}块中的评估错误?

2 个答案:

答案 0 :(得分:2)

正如说明所说,你可能会输入一些内容然后按Enter键。

所以,你发送的是'green\n'。或者也许'green\r\n'

无论哪种方式,'green\n' != 'green''green\r\n' != 'green'

测试这个的好方法是打印出你得到的东西。打印字符串的repr会引用它并转义所有控制字符,因此您将完全看到'green\r\n'而不仅仅是green后跟一个空行,这样更容易解读。 (这也可以让你排除假的\0终结符等。)

您可以通过检查,例如data.rstrip()而不是data来解决此问题。

但是,一旦你这样做,你的程序实际上不会工作,它只会在大部分时间工作,或者在某些情况下 (就像在localhost上测试一样)。这是一个难以捕获的错误的秘诀,需要您在最终找到它们时重写整个应用程序。

recv可能会从单个send获取数据,或者从send获取数据的一半,或者从三个单独的send获取数据。如果您收到'gre''green\r\nbl',则不会进行任何操作以使匹配成为'green'

要解决此问题,您需要设计一种以某种方式界定消息的协议,并循环recv,添加到缓冲区,并拆分消息。或者,如果您的协议只是“使用换行符终止每个命令”(并且命令中没有嵌入的换行符),您可以使用socket.makefile,它会为您提供一个类似文件的对象,可以自动为您执行此操作 - 你可以逐行迭代它(或在它上面调用readline等),就像你可以使用常规文件一样。您甚至可以使用通用换行支持打开它,因此您不必担心讨厌的不一致\r\n\n

有关详细信息,请参阅Sockets are byte streams, not message streams

答案 1 :(得分:1)

这里的问题很可能是从telnet发送换行符。尝试在if块之前删除尾随空格:

data = data.rstrip()