也许这里会有人能够回答我这件事,它让我疯狂。简单来说,我正在制作一种代理。每当它接收到东西时,它都会将所有内容转发到服务器,并发送响应。因此,总是有一个套接字在端口4557上监听客户端,对于每个传入的连接,都会创建一个新的套接字以连接到服务器端口4556上的随机端口。
客户端 <==> 代理 <==> 服务器
另外,还有另一个套接字被实例化并侦听从服务器发出并要转发到相应客户端的请求。
以下是一个示例:
- 客户端A连接到代理的端口4557 - 代理创建一个到服务器端口4556的套接字 - 同时,它创建了一个监听端口40100的套接字 - 客户端发送东西,被转发到服务器 - 客户端断开连接。关闭客户端连接和与服务器的套接字 - 一段时间后,服务器将东西发送到端口40100的代理 - 所有东西都被转发到客户端A(端口40100对应客户端A) - 以此类推...
到目前为止,在我的测试中,我使用一个简单的Python脚本向代理发送唯一的TCP数据包,同时显示接收到的数据并回显。
因此问题是,当与代理的连接关闭时,应该使用“sock.close()”关闭与服务器的连接。然而,它似乎完全被忽略了。套接字仍保持为已建立状态。
现在关于代码的一些说明。
几个注意事项。
- DTN和Node分别是服务器和客户端。 - runCallback在循环中调用,直到线程死亡。 - finalCallback在线程即将死亡时被调用。 - 远程主机(客户端)、代理端口(到服务器)和代理之间的关联保存在字典中:TCPProxyHostRegister(RemoteHost => Proxy)、TCPProxyPortRegister(Port => Proxy)、TCPPortToHost(Port => RemoteHost)。
第一个类是TCPListenerThread。 它只监听特定的端口,并实例化代理(每个Client=>Server couple和Server=>Client couple都有一个),并转发它们的连接。
现在是TCP代理: 它将远程主机(客户端)与连接到服务器的端口关联起来。 如果它是来自新客户端的连接,它将为服务器创建一个新的侦听器(见上文),并创建一个准备将所有内容转发到服务器的套接字。
在这个代理类中,我实例化了两个类,TCPHandlerThread和TCPReplyThread。它们分别负责将数据转发到服务器和将数据转发回客户端。
每当一个连接关闭时,线程就会死亡,代理中的另一个连接(客户端/服务器到代理或代理到服务器/客户端)应该在Proxy.closeConnections()中关闭。
我注意到当closeConnections()是"data = self.proxy.conn.recv(BUFFER_SIZE)"时,它运行良好,但当它被调用时甚至在后面的语句之后,它就会出错。
我使用Wireshark监测了TCP,代理没有发送任何“bye信号”。套接字状态没有转换为TIME_WAIT或其他状态,仍然是ESTABLISHED。
此外,我在Windows和Ubuntu上进行了测试。
- 在Windows上,它正如我所解释的那样。 - 在Ubuntu上,通常可以正常工作(但不总是),连接两次后,第三次以完全相同的方式连接到代理时,它再次出现问题,与我所解释的情况完全相同。
这里是我正在使用的三个文件,这样您就可以查看整个代码。很抱歉代理文件可能不是很容易阅读。本来应该是一个快速开发。
客户端 <==> 代理 <==> 服务器
另外,还有另一个套接字被实例化并侦听从服务器发出并要转发到相应客户端的请求。
以下是一个示例:
- 客户端A连接到代理的端口4557 - 代理创建一个到服务器端口4556的套接字 - 同时,它创建了一个监听端口40100的套接字 - 客户端发送东西,被转发到服务器 - 客户端断开连接。关闭客户端连接和与服务器的套接字 - 一段时间后,服务器将东西发送到端口40100的代理 - 所有东西都被转发到客户端A(端口40100对应客户端A) - 以此类推...
到目前为止,在我的测试中,我使用一个简单的Python脚本向代理发送唯一的TCP数据包,同时显示接收到的数据并回显。
因此问题是,当与代理的连接关闭时,应该使用“sock.close()”关闭与服务器的连接。然而,它似乎完全被忽略了。套接字仍保持为已建立状态。
现在关于代码的一些说明。
几个注意事项。
- DTN和Node分别是服务器和客户端。 - runCallback在循环中调用,直到线程死亡。 - finalCallback在线程即将死亡时被调用。 - 远程主机(客户端)、代理端口(到服务器)和代理之间的关联保存在字典中:TCPProxyHostRegister(RemoteHost => Proxy)、TCPProxyPortRegister(Port => Proxy)、TCPPortToHost(Port => 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)"时,它运行良好,但当它被调用时甚至在后面的语句之后,它就会出错。
我使用Wireshark监测了TCP,代理没有发送任何“bye信号”。套接字状态没有转换为TIME_WAIT或其他状态,仍然是ESTABLISHED。
此外,我在Windows和Ubuntu上进行了测试。
- 在Windows上,它正如我所解释的那样。 - 在Ubuntu上,通常可以正常工作(但不总是),连接两次后,第三次以完全相同的方式连接到代理时,它再次出现问题,与我所解释的情况完全相同。
这里是我正在使用的三个文件,这样您就可以查看整个代码。很抱歉代理文件可能不是很容易阅读。本来应该是一个快速开发。
http://hognerud.net/stackoverflow/
提前感谢你的帮助。这肯定是一些愚蠢的东西,请不要在看到后对我太苛刻 :(