Python TCP服务器与C++客户端之间的通信

4
我在尝试通过Python TCP服务器和C++ TCP客户端进行通信时遇到了问题。 第一次调用正常工作,但随后的调用会出现问题。
就WinSock而言,send()函数工作正常,它返回正确的长度,而WSAGetLastError()不会返回任何重要信息。
然而,当使用wireshark观察数据包时,我注意到第一次调用发送了两个数据包:一个带有所有数据的PSH,ACK包和一个ACK包,但随后的调用(不起作用)只发送PSH,ACK包,没有随后的ACK包。
接收计算机的wireshark证实了这一点,而Python服务器没有任何数据从套接字中输出,我无法进行更深入的调试,因为套接字是本地类。
当我运行C++客户端和C++服务器(一个被黑客复制的Python服务器)时,客户端始终忠实地发送PSH,ACk和ACK包,即使在第一次调用之后也是如此。
Winsock send函数是否应该始终发送PSH,ACK和ACK? 如果是这样,为什么连接到我的C++服务器而不是Python服务器时会这样做? 是否有人遇到过类似的问题?

在服务器的任何一个版本中,您是否看到服务器发送的确认信息?您提到客户端发送了一个不应该发生的 ack,除非您从服务器获取了一些东西。您确定 Python 应用程序行为正常吗? - stonemetal
2个回答

2

客户端发送一个PSH,ACK,然后服务器发送一个PSH,ACK和一个FIN,PSH,ACK。

由于出现了FIN,可能是您的Python版本服务器在初始读取之后立即关闭连接吗?

如果您没有明确关闭服务器套接字,则该服务器的远程套接字变量可能会超出范围,从而关闭它(并且这个bug不存在您的C++版本中)?

假设这是情况,我可以通过以下代码为服务器创建非常相似的TCP序列:

# server.py
import socket
from time import sleep

def f(s):
        r,a = s.accept()
        print r.recv(100)

s = socket.socket()
s.bind(('localhost',1234))
s.listen(1)

f(s)
# wait around a bit for the client to send it's second packet
sleep(10)

对于客户端,需要做以下事情:

# client.py
import socket
from time import sleep

s = socket.socket()
s.connect(('localhost',1234))

s.send('hello 1')
# wait around for a while so that the socket in server.py goes out of scope
sleep(5)
s.send('hello 2')

启动数据包嗅探器,然后运行server.py和client.py。这是tcpdump -A -i lo的输出,与您的观察结果相匹配:

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes
12:42:37.683710 IP localhost:33491 > localhost.1234: S 1129726741:1129726741(0) win 32792 <mss 16396,sackOK,timestamp 640881101 0,nop,wscale 7>
E..<R.@.@...............CVC.........I|....@....
&3..........
12:42:37.684049 IP localhost.1234 > localhost:33491: S 1128039653:1128039653(0) ack 1129726742 win 32768 <mss 16396,sackOK,timestamp 640881101 640881101,nop,wscale 7>
E..<..@.@.<.............C<..CVC.....Ia....@....
&3..&3......
12:42:37.684087 IP localhost:33491 > localhost.1234: . ack 1 win 257 <nop,nop,timestamp 640881102 640881101>
E..4R.@.@...............CVC.C<......1......
&3..&3..
12:42:37.684220 IP localhost:33491 > localhost.1234: P 1:8(7) ack 1 win 257 <nop,nop,timestamp 640881102 640881101>
E..;R.@.@...............CVC.C<......./.....
&3..&3..hello 1
12:42:37.684271 IP localhost.1234 > localhost:33491: . ack 8 win 256 <nop,nop,timestamp 640881102 640881102>
E..4.(@.@...............C<..CVC.....1}.....
&3..&3..
12:42:37.684755 IP localhost.1234 > localhost:33491: F 1:1(0) ack 8 win 256 <nop,nop,timestamp 640881103 640881102>
E..4.)@.@...............C<..CVC.....1{.....
&3..&3..
12:42:37.685639 IP localhost:33491 > localhost.1234: . ack 2 win 257 <nop,nop,timestamp 640881104 640881103>
E..4R.@.@...............CVC.C<......1x.....
&3..&3..
12:42:42.683367 IP localhost:33491 > localhost.1234: P 8:15(7) ack 2 win 257 <nop,nop,timestamp 640886103 640881103>
E..;R.@.@...............CVC.C<......./.....
&3%W&3..hello 2
12:42:42.683401 IP localhost.1234 > localhost:33491: R 1128039655:1128039655(0) win 0
E..(..@.@.<.............C<......P...b...

9 packets captured
27 packets received by filter
0 packets dropped by kernel

这很有可能是问题所在。 我正在使用xmlrpc服务器作为我的Python服务器,它显然是一个单服务实体? - DanJ

1
你发送的数据包有多大?
如果它们很小 - 可能Nagle算法和延迟确认算法是你的烦恼?从你所描述的情况来看,可能涉及到延迟确认...

我告诉Wireshark查看服务器返回的所有内容,发现在第一次发送/接收时,客户端发送了PSH、ACK,然后服务器发送了PSH、ACK和FIN、PSH、ACK,我的客户端回复了PSH、ACK。然后在第二次调用时,我发送了第一个PSH、ACK,服务器响应了RST。我得到了连接重置请求,这是因为服务器没有收到ACK吗?这可能是双缓冲区不足导致的结果吗? - DanJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接