Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python TCP设备不会结束连接,单个设备会结束许多非活动连接_Python_Python 2.7_Sockets_Tcp - Fatal编程技术网

Python TCP设备不会结束连接,单个设备会结束许多非活动连接

Python TCP设备不会结束连接,单个设备会结束许多非活动连接,python,python-2.7,sockets,tcp,Python,Python 2.7,Sockets,Tcp,我有一个奇怪的问题如下 我正在用Python2.7准备一个设备客户端。有一些跟踪设备处于活动状态并正在运行,向服务器发送信号。它们有周期性信号,每小时发送一次。信号发送频率根据情况而变化,但他们必须每小时至少发送一次GPS位置数据信号 这些设备正在长连接模式下运行,这意味着设备启动的连接应保持活动状态3-4小时。为了保持这种连接,你发送的心跳信号不是GPS位置信号,而是包含一些数据的信号。心跳信号间隔为15分钟 下面是我监听TCP端口的脚本 class Server(object): d

我有一个奇怪的问题如下

我正在用Python2.7准备一个设备客户端。有一些跟踪设备处于活动状态并正在运行,向服务器发送信号。它们有周期性信号,每小时发送一次。信号发送频率根据情况而变化,但他们必须每小时至少发送一次GPS位置数据信号

这些设备正在长连接模式下运行,这意味着设备启动的连接应保持活动状态3-4小时。为了保持这种连接,你发送的心跳信号不是GPS位置信号,而是包含一些数据的信号。心跳信号间隔为15分钟

下面是我监听TCP端口的脚本

class Server(object):
    def __init__(self, host, sock_port, buffsize=1024):
        self.hostname = host
        self.sock_port = sock_port
        self.buffsize = buffsize
        self.socket = None

    def start(self):
        self.log.info("Listening: ")
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind((self.hostname, self.sock_port))
        self.socket.listen(1024)

        while True:
            conn, address = self.socket.accept()
            thread.start_new_thread(GV55LiteHandler(conn=conn, buff_size=self.buffsize).handle_data, ())
这是套接字服务器接收新连接时调用的方法:

class GV55LiteHandler():
    ....

    def handle_data(self):
        while True:
            try:
                _veri = self.conn.recv(self.buff_size)
                if not _veri:
                    # We do not recieve any data...
                    raise NoIncomingDataException()
            except NoIncomingDataException:
                break
            except Exception as h_e:
                print h_e
                break
            else:
                self.control_data(_veri)
        self.conn.close()
过了一会儿,我使用psutil检查进程的线程数,发现线程总数大于5.000。我评估这一点是因为有些设备的死连接看起来仍然处于活动状态,但被设备断开,并建立了新连接。考虑到总数,每个设备看起来像创建了4个连接,当设备内的长连接时间设置过多时关闭它们,并建立了一个新连接。这在某些情况下是正常的,没有效果。但是过了一段时间,我收到报告说有些设备无法连接!然后我杀死端口侦听脚本并重新启动它,在10分钟内,所有无法连接和发送数据的设备都会再次开始发送数据。对此进行了一些研究,但找不到任何有关情况的信息。我最好的猜测是,在一个设备建立了太多的连接后,我有一个类似的跟踪设备与另一个制造商,我有大约120个活动设备,看到的线程总数为1600个,这意味着每个设备都建立了连接,但未能断开10个以前的连接,然后建立一个全新的连接,就像以前的一样服务器不接受来自该设备的任何新连接,或者设备无法创建到服务器的新TCP连接,并且GPS数据在脚本重新启动和所有连接断开之前不会发送

这些跟踪设备在单个数据连接上运行。这意味着,任何设备都不能有2个活动数据连接,使用这两个连接发送数据也没有意义

我尝试将TCP连接超时设置为TCP连接,如下所示:

conn, address = self.socket.accept()
conn.settimeout(10800)
并在数据处理脚本中处理此问题:

try:
    _veri = self.conn.recv(self.buff_size)
    if not _veri:
        # We do not recieve any data...
        raise NoIncomingDataException()
except NoIncomingDataException:
    # No need to log anything in here...
    break
except socket_timeout:
    print "Socket Timeout"
    break
这似乎是可行的,现在我没有任何设备,不能发送GPS数据。但另一方面,conn.settimeout没有正确设置连接超时,在一段时间后,在最后一个信号发出30秒后,连接被conn.settimeout超时。我希望它将超时设置为3小时,但它失败了,连接在大约20分钟后中断,并发送一个新的心跳信号以打开新连接,然后是GPS位置信号。GPS信号必须每小时发送一次,但当设置超时时,我每20分钟收到一次信号

我使用阻塞套接字作为默认套接字行为。不要尝试非阻塞套接字,也不要太了解它们

我如何才能摆脱导致设备不发送数据的非活动连接,而不中断设备的长连接模式

更新:在settimeout版本和no timeout版本中,我从未在handle_数据方法中遇到NoIncomingDataException

更新2:我的服务器中有Debian GNU/Linux 6.0.10。 My/etc/sysctl.conf配置:

net.ipv4.tcp_keepalive_time = 60
net.ipv4.tcp_fin_timeout = 60
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_ecn = 0

上面的python行是唯一配置套接字的,因此我只有setsockoptsocket.SOL_socket,socket.SO_REUSEADDR,1。我在python脚本中没有socket.SO的任何配置。\u KEEPALIVE。

至少,如果遇到raise NoIncomingDataException或任何其他异常,您似乎从未调用self.conn.close-因此请确保没有泄漏连接。另外,self.conn.recv是否检测到丢失的心跳?你需要一些方法来检测一个死客户端,这样你就可以关闭它的连接——从代码中看不出你是这么做的。不,我从来没有遇到过这个异常。奇怪的是,这20分钟看起来像一些系统上默认的TCP keepalive超时75000秒。您能否检查套接字上是否启用了TCP keepalive,即您正在使用的操作系统?。如果没有,请尝试启用它。如果启用了该选项,则可以尝试使用较低的值。我需要查找这个,但我非常确定settimeout只影响阻塞操作,它不会在超时后关闭套接字。@谢谢,问题已更新