Python TCP套接字没有关闭?

Python TCP套接字没有关闭?,第1张

概述也许这里有人会对这件事做出回应,这只会让我疯狂. 为了简单起见,我正在做一种代理.只要它收到某些东西,它就会将所有内容转发给服务器,然后发回响应.因此,有一个套接字始终在端口4557上侦听客户端,并且对于每个传入连接,在随机端口上创建一个新套接字以连接到服务器端口4556. 客户< ==>代理< ==>服务器 此外,还有另一个套接字,它被实例化并监听来自服务器的请求并转发到相应的客户端. 这是一个 也许这里有人会对这件事做出回应,这只会让我疯狂.

为了简单起见,我正在做一种代理.只要它收到某些东西,它就会将所有内容转发给服务器,然后发回响应.因此,有一个套接字始终在端口4557上侦听客户端,并且对于每个传入连接,在随机端口上创建一个新套接字以连接到服务器端口4556.

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

此外,还有另一个套接字,它被实例化并监听来自服务器的请求并转发到相应的客户端.

这是一个例子:

>客户端A连接到端口4557上的代理
> Proxy在端口4556上创建一个到服务器的套接字
>除此之外,它还会创建一个侦听端口40100的套接字
>客户端发送内容,转发到服务器
>客户端断开连接.关闭客户端连接和服务器的套接字
>一段时间后,Server将端口40100发送给代理
>所有内容都转发给客户端A(端口40100对应客户端A)
>等等……

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

所以问题是当关闭与代理的连接时,也应该用“sock.close()”关闭与服务器的连接.然而它似乎完全被忽略了.套接字保持为ESTABliSHED.

现在关于代码.

几点说明.

> DTN和Node分别是服务器和客户端.
>在循环中调用runcallback,直到线程死亡.
>当线程死亡时调用finalCallback.
>远程主机(客户端),代理端口(到服务器)和代理之间的关联保存在词典中:TCPProxyHostRegister(RemoteHost =>代理),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或其他任何东西,它只是保持ESTABliSHED.

另外,我在windows和Ubuntu上测试过它.

>在windows上,它完全按照我的解释
>在Ubuntu上,它适用于通常(并非总是),2个连接,并且第三次以完全相同的方式连接到同一客户端到代理,它再次出错,正如所解释的那样.

这是我正在使用的三个文件,以便您可以查看整个代码.对不起,代理文件可能不太容易阅读.被支持成为一个快速的开发者.

http://hognerud.net/stackoverflow/

提前致谢..
这肯定是愚蠢的事.当你看到它时,请不要太用力打我:(

解决方法 首先,我很抱歉我目前没有时间实际运行和测试您的代码.

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

我的猜测是,proxy.conn.recv()函数只返回,实际上是套接字收到的BUFFER_SIZE字节.因此,线程被阻塞,直到收到足够的数据,因此套接字不会被关闭.

正如我先说的那样,这只是一个猜测,所以如果不能解决问题,请不要投票给我.

总结

以上是内存溢出为你收集整理的Python TCP套接字没有关闭?全部内容,希望文章能够帮你解决Python TCP套接字没有关闭?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1192522.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存