Python TCP套接字没有关闭?
也许这里有人会对这件事做出回应,这只会让我疯狂.
为了简单起见,我正在做一种代理.只要它收到某些东西,它就会将所有内容转发给服务器,然后发回响应.因此,有一个套接字始终在端口4557上侦听客户端,并且对于每个传入连接,在随机端口上创建一个新套接字以连接到服务器端口4556. 客户< ==>代理< ==>服务器 此外,还有另一个套接字,它被实例化并监听来自服务器的请求并转发到相应的客户端. 这是一个例子: >客户端A连接到端口4557上的代理 到目前为止,在我的测试中,我使用一个简单的python脚本向代理发送一个唯一的tcp数据包,以及一个显示接收数据并回显的转储服务器. 所以问题是当关闭与代理的连接时,也应该用“sock.close()”关闭与服务器的连接.然而它似乎完全被忽略了.套接字保持为ESTABLISHED. 现在关于代码. 几点说明. > DTN和Node分别是服务器和客户端. 第一个类是TCPListenerThread. class TCPListenerThread(StoppableThread): def __init__(self,tcp_port): StoppableThread.__init__(self) self.tcp_port = tcp_port self.sock = socket.socket( socket.AF_INET,# Internet socket.SOCK_STREAM ) # tcp self.sock.bind( (LOCAL_ADDRESS,self.tcp_port) ) self.sock.listen(1) def runCallback(self): print "Listen on "+str(self.tcp_port)+".." conn,addr = self.sock.accept() if isFromDTN(addr): tcpProxy = getProxyFromPort(tcp_port) if not tcpProxy: tcpProxy = TCPProxy(host,True) else: host = addr[0] tcpProxy = getProxyFromHost(host) if not tcpProxy: tcpProxy = TCPProxy(host,False) tcpProxy.handle(conn) def finalCallback(self): self.sock.close() 现在来了TCP代理: class TCPProxy(): def __init__(self,remote,isFromDTN): #remote = port for Server or Remote host for Client self.isFromDTN = isFromDTN self.conn = None #add itself to proxy registries #If listening from a node if not isFromDTN: #Set node remote host self.remoteHost = remote TCPProxyHostRegister[self.remoteHost] = self #Set port to DTN interface + listener self.portToDTN = getNewTCPPort() TCPPortToHost[self.portToDTN] = self.remoteHost newTCPListenerThread(self.portToDTN) #Or from DTN else: self.portToDTN = remote TCPProxyPortRegister[self.portToDTN] = self self.remoteHost = getRemoteHostFromPortTCP(self.portToDTN) def handle(self,conn): print "New connection!" #shouldn't happen,but eh if self.conn != None: self.closeConnections() self.conn = conn #init socket with remote self.sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #self.sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) if self.isFromDTN: self.sock.connect((self.remoteHost,4556)) #TODO: handle dynamic port.. else: self.sock.connect((DTN_Address,DTN_TCPPort)) #handle connection in a thread self.handlerThread = newTCPHandlerThread(self) #handle reply in a therad self.replyThread = newTCPReplyThread(self) def closeConnections(self): try: if self.conn != None: print "Close connections!" self.sock.close() self.conn.close() self.conn = None self.handlerThread.kill() self.replyThread.kill() except Exception,err: print str(err) #pass def forward(self,data): print "TCP forwarding data: "+data self.sock.send(data) def forwardBack(self,data): print "TCP forwarding data back: "+data self.conn.send(data) 在这个代理类中,我实例化了两个类,TCPHandlerThread和TCPReplyThread.他们分别负责转发到服务器并转发回客户端. class TCPHandlerThread(StoppableThread): def __init__(self,proxy): StoppableThread.__init__(self) self.proxy = proxy def runCallback(self): test = False while 1: data = self.proxy.conn.recv(BUFFER_SIZE) if test: self.proxy.sock.close() test = True if not data: break print "TCP received data:",data self.proxy.forward(data) self.kill() def finalCallback(self): self.proxy.closeConnections() class TCPReplyThread(StoppableThread): def __init__(self,proxy): StoppableThread.__init__(self) self.proxy = proxy def runCallback(self): while 1: data = self.proxy.sock.recv(BUFFER_SIZE) if not data: break print "TCP received back data: "+data self.proxy.forwardBack(data) self.kill() def finalCallback(self): self.proxy.closeConnections() 您会看到,只要连接关闭,线程就会死掉,而另一个连接(客户端/服务器到代理或代理到服务器/客户端)应该在Proxy.closeConnections()中关闭 我注意到当closeConnections()是“data = self.proxy.conn.recv(BUFFER_SIZE)”时,它运行良好,但是当它在后一个语句之后被调用时,它就会出错. 我使用TCP线路,代理不发送任何“再见信号”.套接字状态不会转到TIME_WAIT或其他任何东西,它只是保持ESTABLISHED. 另外,我在Windows和Ubuntu上测试过它. >在Windows上,它完全按照我的解释 这是我正在使用的三个文件,以便您可以查看整个代码.对不起,代理文件可能不太容易阅读.被支持成为一个快速的开发者. http://hognerud.net/stackoverflow/ 提前致谢.. 解决方法
首先,我很抱歉我目前没有时间实际运行和测试您的代码.
但是我想到了这个想法,你的问题实际上可能与套接字上使用阻塞模式和非阻塞模式有关.在这种情况下,您应该检查python文档中的“socket”模块帮助,尤其是socket.setblocking(). 我的猜测是,proxy.conn.recv()函数只返回,实际上是套接字收到的BUFFER_SIZE字节.因此,线程被阻塞,直到收到足够的数据,因此套接字不会被关闭. 正如我先说的那样,这只是一个猜测,所以如果不能解决问题,请不要投票给我. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |