我有Python 2.7.12代码,它等待来自外部设备的连接,然后旋转一个线程来处理每个设备。 80%的时间这个工作正常,但每隔一段时间我从操作系统或Python中得到不需要的RST,我不确定是哪一个。
TCP连接正常启动,然后重置abrubptly。
SYN,SYN / ACK,ACK,RST
服务器启动RST。时机也非常紧张所以我觉得这可能是Python的套接字漏洞或操作系统由于某种原因而接管。我怎么调试这个?由于我没有在Python代码中看到任何错误并记录自己,有没有办法调试Python直接使用的套接字代码?
以下是代码:
while True:
host = socket.gethostbyname(socket.gethostname())
port = 3001
try:
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((host,port))
tcpsock.listen(5)
print ("\nListening for incoming connections...")
(clientsock, (ip, port)) = tcpsock.accept()
newthread = ClientThread(ip, port, clientsock)
newthread.start()
threads = 0
for t in threading.enumerate():
threads += 1
logger.info('######################## THREADS = %s' % (threads))
except Exception as e:
logger.critical('Exception: %s. Error initializing thread' % (e))
EDIT1 - 添加ClientThread代码:
class ClientThread(threading.Thread):
def __init__(self,ip,port,clientsocket):
threading.Thread.__init__(self)
self.ip = ip
self.port = port
self.csocket = clientsocket
其余代码才开始使用该设备。
答案 0 :(得分:0)
RST数据包的意思是“我没有为您刚刚发送给我的数据包打开连接”。没错,如果您遵循python.org上的简单示例,那么Python将生成RST数据包。例如:
#!/usr/bin/python2.7
import socket, sys, time
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Bind the socket to the port
server_port = 10000
print 'starting up on port %s' % server_port
sock.bind(('', server_port))
# Listen for incoming connections
sock.listen(1)
print 'waiting for a connection'
conn, cli_addr = sock.accept()
print 'connection from', cli_addr
data = "Hello, World!\n" \
+ "Your IP is " + cli_addr[0] + "\n"
HTTP = "HTTP/1.1 200 OK\nContent-Type: text/html\nContent-Length:"
conn.sendall(HTTP + str(len(data)) + "\n\n" + data);
conn.close()
tcpdump
然后说:
10:59:48.847443 IP 127.0.0.1.38330 > 127.0.0.1.10000: Flags [S], seq 1326297161, win 43690, options [mss 65495,sackOK,TS val 3126487416 ecr 0,nop,wscale 7], length 0
10:59:48.847462 IP 127.0.0.1.10000 > 127.0.0.1.38330: Flags [S.], seq 1677934801, ack 1326297162, win 43690, options [mss 65495,sackOK,TS val 3126487416 ecr 3126487416,nop,wscale 7], length 0
10:59:48.847475 IP 127.0.0.1.38330 > 127.0.0.1.10000: Flags [.], ack 1, win 342, options [nop,nop,TS val 3126487416 ecr 3126487416], length 0
10:59:48.847547 IP 127.0.0.1.38330 > 127.0.0.1.10000: Flags [P.], seq 1:80, ack 1, win 342, options [nop,nop,TS val 3126487416 ecr 3126487416], length 79
10:59:48.847557 IP 127.0.0.1.10000 > 127.0.0.1.38330: Flags [.], ack 80, win 342, options [nop,nop,TS val 3126487416 ecr 3126487416], length 0
10:59:48.847767 IP 127.0.0.1.10000 > 127.0.0.1.38330: Flags [P.], seq 1:95, ack 80, win 342, options [nop,nop,TS val 3126487416 ecr 3126487416], length 94
10:59:48.847790 IP 127.0.0.1.38330 > 127.0.0.1.10000: Flags [.], ack 95, win 342, options [nop,nop,TS val 3126487416 ecr 3126487416], length 0
10:59:48.847861 IP 127.0.0.1.10000 > 127.0.0.1.38330: Flags [R.], seq 95, ack 80, win 342, options [nop,nop,TS val 3126487416 ecr 3126487416], length 0
10:59:48.847862 IP 127.0.0.1.38330 > 127.0.0.1.10000: Flags [F.], seq 80, ack 95, win 342, options [nop,nop,TS val 3126487416 ecr 3126487416], length 0
10:59:48.847878 IP 127.0.0.1.10000 > 127.0.0.1.38330: Flags [R], seq 1677934896, win 0, length 0
问题在于conn.close()
破坏了套接字数据结构,因此OS无法识别下一个数据包。请注意,客户端(curl
正在发送一个不错的FIN数据包,但服务器(上面的Python代码)却没有。
要解决此问题,您需要通过调用conn.shutdown(socket.SHUT_WR)
发送FIN数据包,然后将套接字结构保留足够长的时间以捕获任何散乱的数据包(您可以在另一个线程中执行此操作)。因此,请执行以下操作,而不要使用conn.close()
:
conn.shutdown(socket.SHUT_WR)
time.sleep(1)
conn.close()
通过此更改,双方发送FIN,tcpdump
中缺少RST:
11:05:50.201352 IP 127.0.0.1.38338 > 127.0.0.1.10000: Flags [S], seq 4249130338, win 43690, options [mss 65495,sackOK,TS val 3126848770 ecr 0,nop,wscale 7], length 0
11:05:50.201368 IP 127.0.0.1.10000 > 127.0.0.1.38338: Flags [S.], seq 1410528158, ack 4249130339, win 43690, options [mss 65495,sackOK,TS val 3126848770 ecr 3126848770,nop,wscale 7], length 0
11:05:50.201381 IP 127.0.0.1.38338 > 127.0.0.1.10000: Flags [.], ack 1, win 342, options [nop,nop,TS val 3126848770 ecr 3126848770], length 0
11:05:50.201441 IP 127.0.0.1.38338 > 127.0.0.1.10000: Flags [P.], seq 1:80, ack 1, win 342, options [nop,nop,TS val 3126848770 ecr 3126848770], length 79
11:05:50.201450 IP 127.0.0.1.10000 > 127.0.0.1.38338: Flags [.], ack 80, win 342, options [nop,nop,TS val 3126848770 ecr 3126848770], length 0
11:05:50.201568 IP 127.0.0.1.10000 > 127.0.0.1.38338: Flags [P.], seq 1:95, ack 80, win 342, options [nop,nop,TS val 3126848770 ecr 3126848770], length 94
11:05:50.201594 IP 127.0.0.1.38338 > 127.0.0.1.10000: Flags [.], ack 95, win 342, options [nop,nop,TS val 3126848770 ecr 3126848770], length 0
11:05:50.201643 IP 127.0.0.1.10000 > 127.0.0.1.38338: Flags [F.], seq 95, ack 80, win 342, options [nop,nop,TS val 3126848770 ecr 3126848770], length 0
11:05:50.201691 IP 127.0.0.1.38338 > 127.0.0.1.10000: Flags [F.], seq 80, ack 96, win 342, options [nop,nop,TS val 3126848770 ecr 3126848770], length 0
11:05:50.201707 IP 127.0.0.1.10000 > 127.0.0.1.38338: Flags [.], ack 81, win 342, options [nop,nop,TS val 3126848770 ecr 3126848770], length 0