簡體   English   中英

在子進程之后關閉套接字。只要子進程仍在運行,Popen會將套接字留在TIME_WAIT中

[英]Closing socket after subprocess.Popen leaves socket in TIME_WAIT as long as child process is still running

在Windows 7上:

給定此服務器代碼:

# 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上不會發生這種情況。

啟用S​​O_REUSEADDR只會使錯誤消失,但是客戶端無法訪問服務器。

在上面的示例中,我專門讓客戶端首先關閉,這樣服務器套接字就不會進入TIME_WAIT。

所以問題是:

  1. 我是否在服務器上遇到TIME_WAIT問題?
  2. 服務器中是否未關閉任何套接字/文件描述符?
  3. 為什么在這種情況下SO_REUSEADDR沒有幫助? 客戶端可以來自同一端口嗎?
  4. 子進程可以掛在某些描述符上嗎?
  5. 我該怎么辦?

解決方案:

問題在於計算器的父進程保留了一些文件描述符。 因此,將close_fds = True添加到Popen將確保所有內容均正確釋放。

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

在子進程之后關閉套接字。只要子進程仍在運行,Popen會將套接字留在TIME_WAIT中

不,不是。 它將它留在TIME_WAIT中固定的時間,即2或4分鍾。 關閉之后,它與子進程完全無關。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM