Python TCP SocketServer及Windows与Unix客户端的区别
我觉得这个问题很基础,但我在网上搜索时没有找到具体的答案。我的问题是关于Windows和Unix的TCP客户端在socket通信上的差异。如果我运行下面这个非常简单的TCP服务器代码,并通过BSD、macOS或Linux用telnet或netcat建立连接(比如telnet remotehost 9997),我可以输入一行文本,然后按下换行键(\r\n),服务器就会回应。
但是,当我从Windows XP客户端通过telnet应用程序(或者用putty的telnet)建立连接时,我能连接上,但只能输入一个字符,服务就会返回响应。我知道Windows和Unix的网络协议栈在处理socket时有所不同,但奇怪的是,从我的数据包捕获来看,我没有看到Windows客户端添加换行符。
示例代码:
import SocketServer as socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.request.send("Welcome\r\n")
self.data = self.request.recv(1024).strip()
print("%s wrote:" % self.client_address[0])
print(self.data)
self.request.send(self.data.upper())
if __name__ == "__main__":
server = socketserver.TCPServer(('', 9997), MyTCPHandler)
server.serve_forever()
这是从Windows客户端连接时服务器端的数据包捕获。0x62(b)是我在尝试输入“blah”时输入的字符。
0000 00 00 00 01 00 06 00 23 33 74 d5 3f 00 00 08 00 .......# 3t.?....
0010 45 00 00 35 77 86 40 00 3c 06 02 5a 0a 0e 14 29 E..5w.@. <..Z...)
0020 0a 03 9c a9 c6 0e 27 0d 20 ed 36 de 87 f2 30 a2 ......'. .6...0.
0030 80 18 ff ff 48 ee 00 00 01 01 08 0a 08 00 46 01 ....H... ......F.
0040 94 f6 26 6f 62 ..&ob
服务器的回应是0x42(B)。
0000 00 04 00 01 00 06 00 50 56 86 1a 4e 00 00 08 00 .......P V..N....
0010 45 00 00 35 16 fd 40 00 40 06 5e e3 0a 03 9c a9 E..5..@. @.^.....
0020 0a 0e 14 29 27 0d c6 0e 87 f2 30 a2 20 ed 36 df ...)'... ..0. .6.
0030 80 18 00 b5 c5 0a 00 00 01 01 08 0a 94 f6 29 a0 ........ ......).
0040 08 00 46 01 42 ..F.B
这是从Unix客户端(netcat remotehost 9997)捕获的数据包,我输入字母t(0x74),并且需要强制按下换行键,这样就生成了0x0d0a。
0000 00 00 00 01 00 06 00 23 33 74 d5 3f 00 00 08 00 .......# 3t.?....
0010 45 00 00 37 ee d2 40 00 3c 06 8b 0b 0a 0e 14 29 E..7..@. <......)
0020 0a 03 9c a9 c6 10 27 0d 69 ac 8e d6 b8 7b 92 b4 ......'. i....{..
0030 80 18 ff ff c4 b1 00 00 01 01 08 0a 08 00 48 1d ........ ......H.
0040 94 f6 59 2b 74 0d 0a ..Y+t..
所以我的问题是,如何让这个socket服务器能够与Windows客户端正常工作?或者我在Windows环境中需要做什么改变,才能让我传递一串字符。
1 个回答
1
它的工作方式是符合预期的(程序不会按照我们的想法去做,它们只会按照我们告诉它们去做的方式去做)。如果你想知道如何让Windows XP的telnet发送CRLF(回车换行),你可以设置相应的选项:
telnet
set ?
set crlf
open <host> <port>
不过我觉得你应该重新考虑一下你的代码,因为服务器并不是按行读取数据,而是尝试读取1024个字节。
这个链接很有帮助。