Python TCP套接字不关闭?

2024-10-01 15:37:07 发布

您现在位置:Python中文网/ 问答频道 /正文

也许这里有人会对这件事有反应,这件事让我发疯。在

简单地说,我做了一个代理。每当它接收到某个信息时,它会将所有内容转发给服务器,并发回响应。因此,有一个套接字总是监听客户机的端口4557,对于每个传入的连接,都会在随机端口上创建一个新的套接字来连接服务器端口4556。在

客户端<;==>;代理服务器

另外,还有另一个socket被实例化并监听来自服务器的请求并被转发到相应的客户端。在

下面是一个例子:

  • 客户机A连接到端口4557上的代理
  • 代理在端口4556上创建到服务器的套接字
  • 同时,它还创建了一个侦听端口40100的套接字
  • 客户端发送内容,转发到服务器
  • 客户端断开连接。关闭客户端连接和服务器的套接字
  • 一段时间后,服务器将数据发送到端口40100上的代理服务器
  • 一切都被转发到客户端A(端口40100对应于客户端A)
  • 等等。。在

到目前为止,在我的测试中,我使用一个简单的python脚本向代理发送一个惟一的tcp包,以及一个显示接收到的数据并回送的转储服务器。在

因此,问题在于当与代理的连接关闭时,与服务器的连接也应使用“关闭”袜子。关上()". 然而,它似乎完全被忽视了。插座保持不变。在

关于代码。

几句话。在

  • 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代理: 它将远程主机(客户端)与连接到服务器的端口相关联。 如果是来自新客户机的连接,它将为服务器创建一个新的侦听器(见上文),并创建一个套接字,准备将所有内容转发给服务器。在

^{pr2}$

在这个代理类中,我实例化了两个类,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)“,它运行得很好,但即使在后一个语句之后调用它,它也会出错。在

我用wiresharkedtcp,代理不发送任何“再见信号”。套接字状态不会转到TIME_WAIT或其他任何状态,它只是保持建立状态。在

另外,我在Windows和Ubuntu上进行了测试。在

  • 在Windows上它和我解释的一模一样
  • 在Ubuntu上,它通常(不总是)工作,2个连接,第三次我用与代理完全相同的方式连接同一个客户机时,它又出了问题。在

下面是我使用的三个文件,这样您可以查看整个代码。很抱歉,代理文件可能不太容易阅读。应该是一个快速发展

http://hognerud.net/stackoverflow/

提前谢谢。。 这肯定是件蠢事。当你看到它时,请不要打得太重


Tags: 端口gtself服务器客户端代理data客户机
1条回答
网友
1楼 · 发布于 2024-10-01 15:37:07

首先,我很抱歉,我目前没有时间实际运行和测试您的代码。在

但是我想到了一个想法,你的问题实际上可能与在套接字上使用阻塞模式和非阻塞模式有关。在这种情况下,您应该签出python文档中的“socket”模块帮助,尤其是插座.立根锁紧(). 在

我猜,那代理连接接收()函数只返回套接字接收的缓冲区大小字节。因此,线程被阻塞,直到收到足够的数据,因此套接字不会关闭。在

正如我先说的,这只是一个猜测,所以请不要投我反对票,如果它不能解决问题。。。在

相关问题 更多 >

    热门问题