2013-07-12 34 views
1

在Windows 7:关闭插座subprocess.Popen叶TIME_WAIT套接字后,只要子进程仍在运行

鉴于这种服务器代码:

# in server.py 
if __name__ == '__main__': 
    serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    # uncommenting this won't help 
    #serversock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
    serversock.bind(('',8888)) 
    serversock.listen(5) 

    # accept and receive dummy data from client 
    clientsock,address = serversock.accept() 
    data = clientsock.recv(1024) 

    # as long as calc.exe is running, I can't do this again 
    subprocess.Popen(r"c:\windows\system32\calc.exe") 

    # letting client close first still won't help 
    time.sleep(3) 

    # closing won't help either 
    clientsock.close() 
    serversock.close() 

而且客户端代码

# in client.py 
if __name__ == '__main__': 
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    s.connect(('127.0.0.1', 8888)) 
    s.sendall('Hello, world') 
    # close early to help prevent TIME_WAIT on server, but doesn't help 
    s.close() 

先运行服务器,然后客户端将启动计算器应用程序。

虽然计算器应用程序仍在运行,但我无法再运行服务器。它会抱怨

python server.py (ok) 
python client.py (ok) 
python server.py (boom!) 
socket.error: [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted 

如果我关闭计算器应用,正在运行的服务器再次确定... 这不会在Mac上发生。

启用SO_REUSEADDR只会使错误消失,但服务器无法从客户端访问。

在上面的示例中,我特别让客户端先关闭,以便服务器套接字不会进入TIME_WAIT。

所以问题:

  1. 我正在运行到服务器上的TIME_WAIT问题?
  2. 任何套接字/文件描述符在服务器中保持未关闭状态吗?
  3. 为什么SO_REUSEADDR在这种情况下不起作用?客户端可以来自同一个端口吗?
  4. 孩子进程可以挂在一些描述符上吗?
  5. 我该怎么办?

解决方案:

与计算器的持有一些文件描述符父进程的问题。 因此,向Popen添加close_fds = True将确保一切正常释放。

subprocess.Popen(r"c:\windows\system32\calc.exe", close_fds=True) 

回答

0

关闭插座subprocess.Popen叶TIME_WAIT套接字后,只要子进程仍在运行

不,它不需要。它会在TIME_WAIT中保留一段固定的时间,2或4分钟。结束后,它完全与儿童进程无关。

+0

它不会释放套接字(至少在Windows中)。 close_fds = True解决了这个问题,用这个集合,我甚至不需要SO_REUSEADDR。 – Paul