Python TCP套接字无法关闭?
|
也许有人会对此事做出回应,这让我发疯了。
为简单起见,我正在创建一种代理。每当它接收到某些东西时,它就会将所有内容转发到服务器,并发送回响应。因此,总是有一个套接字在端口4557上监听客户端,对于每个传入的连接,在随机端口上创建了一个新的套接字,以连接到服务器端口4556。
客户端<==>代理<==>服务器
另外,还有另一个套接字,该套接字被实例化并侦听来自服务器的请求并转发给相应的客户端。
这是一个例子:
客户端A连接到端口4557上的代理
代理在端口4556上为服务器创建套接字
伴随着它,它创建了一个监听端口40100的套接字
客户端发送东西,转发给服务器
客户端断开连接。关闭客户端连接和服务器套接字
一段时间后,服务器将内容发送到端口40100上的代理
一切都转发到客户端A(与客户端A相对应的端口40100)
等等..
到目前为止,在我的测试中,我使用一个简单的python脚本将唯一的tcp数据包发送到代理,以及转储服务器显示接收到的数据并回显。
因此,问题在于,当关闭与代理的连接时,也应使用\“ sock.close()\”关闭与服务器的连接。但是,它似乎完全被忽略了。套接字保持为ESTABLISHED。
现在关于代码。
一些注意事项。
DTN和Node分别是服务器和客户端。
在循环中调用runCallback,直到线程死亡。
线程快死时将调用finalCallback。
字典中保留了远程主机(客户端),代理端口(到服务器)和代理之间的关联:TCPProxyHostRegister(远程主机=>代理),TCPProxyPortRegister(端口=>代理),TCPPortToHost(端口=> RemoteHost)。
第一类是TCPListenerThread。
它仅侦听特定端口并实例化代理(每个Client => Server couple和Server => Client couple一个)并转发它们的连接。
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或其他任何状态,只是保持已建立状态。
另外,我在Windows和Ubuntu上进行了测试。
在Windows上,完全按照我的解释
在Ubuntu上,通常(并非总是),2个连接都可以很好地工作,并且第三次我以完全相同的方式与代理连接到相同的客户端时,再次出现错误,如所解释的那样。
这是我正在使用的三个文件,因此您可以查看整个代码。抱歉,代理文件可能不太容易阅读。应该是一个快速的开发者。
http://hognerud.net/stackoverflow/
提前致谢..
这肯定是愚蠢的。看到它时,请不要用力打我:(
没有找到相关结果
已邀请:
1 个回复
扑北爱