python - 只要子进程仍在运行,subprocess.Popen 后关闭套接字就会在 TIME_WAIT 中留下套接字

标签 python sockets networking tcp subprocess

在 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 上。

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

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

所以问题:

  1. 我是否在服务器上遇到了 TIME_WAIT 问题?
  2. 服务器中是否有未关闭的套接字/文件描述符?
  3. 为什么 SO_REUSEADDR 在这种情况下没有帮助?客户端可能来自同一个端口吗?
  4. 子进程是否可以卡在某些描述符上?
  5. 我该怎么办?

解决方案:

问题在于 Calculator 的父进程持有某个文件描述符。 因此,将 close_fds=True 添加到 Popen 将确保一切都正确发布。

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

最佳答案

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

不,它没有。它将它留在 TIME_WAIT 中一段固定的时间,2 或 4 分钟。关闭后与子进程完全没有关系。

关于python - 只要子进程仍在运行,subprocess.Popen 后关闭套接字就会在 TIME_WAIT 中留下套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17606740/

相关文章:

python - settings.DEBUG 的值在 Django 测试中的设置和 url 之间变化

c - 如何初始化缓冲区

java - 在 HttpUrlConnection 中设置自定义套接字实现

javascript - 如何使用本地网络中的 Node 后端访问我的 React 应用程序?

python - 使用Open CV删除背景并不精确,并且某些图片无法正确处理

python - Scipy.signal.spectrogram输出长度

python - 在 kivy 中更改按钮或标签文本颜色

Java:服务器/客户端 -> 客户端/客户端

java - 影响 Linux 上 Java 6 中 NetworkInterface.getNetworkInterfaces 枚举的顺序

c - struct tcphdr 和 struct tcp 的区别