我正在学习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}}块中的评估错误?
答案 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
。
答案 1 :(得分:1)
这里的问题很可能是从telnet发送换行符。尝试在if
块之前删除尾随空格:
data = data.rstrip()