Python 接受的套接字连接未关闭

Python accepted socket connection not closing

我编写了一个 Pi 硬件接口服务器 (phis),它使用 http 协议来控制连接到我的 Raspberry Pi 的硬件(继电器、模拟测量等)。它处理简单的请求并以纯文本响应。它多年来一直完美无缺地工作,我已经为系统编写了广泛的 browser-based 接口。这是基本结构:

listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listen_socket.bind((HOST, PORT))
listen_socket.listen(1)

read_list = [listen_socket]

while True:
    readable, writeable, errored = select.select(read_list,[], [], 2)
    if len(readable) == 0: # select timed out
        continue

    client_connection, client_address = listen_socket.accept()
    try:
        request = client_connection.recv(1024)
    except Exception:
        print "Exception trying to recv, %s" % time.strftime(date_format)
        sys.exc_clear()
        client_connection.close()
        continue

    words = request.split()

    http_response = """\
HTTP/1.1 200 OK
"""
    try:
        client_connection.sendall(http_response)
    except Exception:
        print "Exception trying to send 1, %s" % time.strftime(date_format)
        sys.exc_clear()
        client_connection.close()
        continue

    http_response = """\
Content-Type: text/plain; charset=utf-8

"""

# perform some action and add text to the http_response (like current CPU temperature, etc)

    try:
        client_connection.sendall(http_response)
    except Exception:
        # log the error, then...
        sys.exc_clear()
        client_connection.close()
        continue

    client_connection.close()

    if words[1] == '/exit':
        sys.exit(0)

命令启动时出现问题mjpg_streamer。流开始很好,响应已发送,我可以建立更多连接并发出新命令,但 client_connection.close() 从未真正关闭连接,浏览器只是坐在那里等待更多永远不会到来的东西。 phis 仍在接受新连接并为这些连接提供服务,但是如果我使用请求“http://pi:4000/exit”退出服务器,它会干净利落,但它不会再次启动(正在使用套接字),除非我先发出停止请求 mjpg_streams(也可以正常工作)。

mjpg_streamer 已经在(似乎是)守护进程后台模式下启动,但在我尝试让它工作的过程中,我已经发出命令在每个 python 启动它你的背景 child 并保留它 运行” 我可以找到的方法 (os.system(), subprocess.Popen(), os.fork() 和 os.fork () 两次,中间有 os.setsid())。没有任何效果。

如果重要的话,我实际上是从 mjpg_steamer 开始的 phis 调用一个 perl 脚本,命令行参数基于传递给 perl 脚本的参数。

我在谷歌上搜索了很多,发现其他人的连接不会关闭,但连接不会完全关闭,除非在连接处于活动状态时生成一些后台 socket-based 应用程序。任何人都知道出了什么问题吗?

中找到了答案(我看到它的那一刻就“呸”了一声!)

我忘记关闭分叉子进程中的已连接和正在侦听的套接字,这些套接字由生成的守护进程继承并在运行期间一直保持打开状态。这是我用来生成一个进程的代码,该进程将被保留 运行(守护进程):

def spawnDaemon(syscmd):
    # do the UNIX double-fork magic, see Stevens' "Advanced 
    # Programming in the UNIX Environment" for details (ISBN 0201563177)
    try: 
        pid = os.fork() 
        if pid > 0:
            # parent process, wait for first child, then return and keep running
            os.wait()
            #print "first parent returning"
            return
    except OSError, e:
        print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1)

    # close the copy of the socket the request came in on
    client_connection.close()

    # close the copy of the server's main listening socket
    listen_socket.close()

    # change process group to detach the child (mjpeg_streamer) from the parent phis
    os.setsid()

    # do second fork
    #print "trying second fork"
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit from second parent
            #print "second parent exiting"
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1)

    # execute the command
    os.system(syscmd)

    # all done, exit 2nd child
    #print "exiting after executing syscmd"
    sys.exit(0)
# spawnDaemon()