繁体   English   中英

为什么线程中的python套接字无法始终正确关闭(即,如果我连续多次运行该程序)

[英]Why does my python socket in a thread not always close properly (i.e. if i run the program many times in a row)

我有以下代码(可能带有调试消息)。 如果我连续运行几次(彼此之间几秒钟之内),我经常会收到一个地址使用错误。 并非每次都发生。

socket.error: [Errno 98] Address already in use

当我没有收到错误时,输出为:

 trying to recv ('127.0.0.1', 38041)
 recved
 from client -->  None genuine without this seal!
 shutting down con
 closing con
 done closing con
 shutting down
 running server shutdown
 running server close
 done closing
 done shutting down

以下是我的代码:

import socket
from threading import Thread
from time import sleep
from subprocess import Popen, PIPE, STDOUT


def shutdown_thread(t):
    print "shutting down"
    t.shutdown()
    while t.isAlive():
        sleep(.1)
    print "done shutting down"


def send_with_netcat(msg):
    nc = Popen(
        ['nc', '127.0.0.1', '8000'],
        stdin=PIPE,
        stdout=PIPE,
        stderr=STDOUT)

    result = nc.communicate(msg)
    return result


class Server(Thread):
    is_shutdown = False

    def __init__(self):
        super(Server, self).__init__()
        self.start_server()

    def start_server(self):
        self.server = socket.socket(
            socket.AF_INET,
            socket.SOCK_STREAM)

        # "A socket is a 5 tuple (proto, local addr, local port,
        # remote addr, remote port).  SO_REUSEADDR just says that you
        # can reuse local addresses.  The 5 tuple still must be
        # unique!"
        self.server.setsockopt(
            socket.SOL_SOCKET,
            socket.SO_REUSEADDR,
            1)

        self.server = socket.socket(
            socket.AF_INET,
            socket.SOCK_STREAM)

        # bind the socket
        # ERROR HAPPENS HERE, HOW TO DEAL DEAL WITH OR AVOID?
        self.server.bind(('127.0.0.1', 8000))
        self.server.listen(5)

    def shutdown(self):
        self.is_shutdown = True

    def run(self):
        while not self.is_shutdown:
            con, addr = self.server.accept()
            print "trying to recv", addr
            buf = con.recv(128)
            print "recved"
            if len(buf) > 0:
                print "from client --> ", buf

            print "shutting down con"
            con.shutdown(socket.SHUT_RDWR)
            print "closing con"
            con.close()
            print "done closing con"
            sleep(.1)

        print "running server shutdown"
        self.server.shutdown(socket.SHUT_RDWR)
        print "running server close"
        self.server.close()
        print "done closing"

if __name__ == '__main__':
    s = Server()
    s.start()
    send_with_netcat("None genuine without this seal!")
    shutdown_thread(s)
    sleep(5)

如果您发现github更具可读性,则可以在此处看到相同的代码

奇怪的是,当我尝试发布此帖子时,可能需要花费更多的时间。 可能是因为我的计算机上发生了更多连接以随机化客户端nc连接吗?

感谢您对此问题的任何澄清。

start_server()方法中,您将在self.server打开一个套接字,然后在此套接字上设置SO_REUSEADDR ,然后再次调用socket.socket() ,这将删除您的setsockopt()调用。 尝试删除第二个socket.socket()调用。 这应该使SO_REUSEADDR标志生效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM