Last active
June 29, 2022 09:09
-
-
Save Zheaoli/108546daf349de358761f9f8b9664a53 to your computer and use it in GitHub Desktop.
Connection in Use Case
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import socket | |
import time | |
s = socket.socket() | |
host = "127.0.0.1" | |
port = 12345 | |
s.connect((host, port)) | |
print(s.recv(1024).decode()) | |
time.sleep(10000000) | |
s.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import socket | |
import time | |
import os | |
def abc(): | |
s = socket.socket() | |
host = "127.0.0.1" | |
port = 12345 | |
s.bind((host, port)) | |
# print(s.error) | |
s.listen(5) | |
while True: | |
c, addr = s.accept() | |
print("连接地址:", addr) | |
c.send("Manjusaka!".encode()) | |
break | |
s.close() | |
while True: | |
abc() | |
time.sleep(1) |
这个问题和客户端无关, 就算客户端在收到 fin 之后及时 close, 服务端也会残留 TIME_WAIT 导致 address in use.
你的最小复现代码里, 把 client.py 里的 sleep 删掉一样可以复现, 足以证明和客户端行为无关, 只是残留状态一个是 TIME_WAIT 一个是 FIN_WAIT2, 这是 TCP 的设计.
解决这个问题要用 SO_REUSEADDR 和 SO_REUSEPORT.
@jschwinger233 嗯,是的,最终的解法是 SO_REUSEADDR/SO_REUSEPORT
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
这个问题差不多是这样
服务端主动关闭 socket 之后,走了一系列调用
调用栈参考上面的,在 tcp_close 后,主动给客户端发送一个 FIN 后进入 FIN_WAIT1 状态(实际上是先把内核的 socket 对象设置为 FIN_WAIT1 ,然后再调用 tcp_send_fin 发送 FIN),在收到 ACK 后进入 FIN_WAIT2 状态。由于客户端各种原因一直没有 close,导致 server 侧一直处于一个 FIN_WAIT2 的状态,进而一直占用一个 socket(但是这个 socket 关联的文件描述符已经提前释放)(等待 2MSL 后释放),导致 server 端重启后会出现 Bind 失败的问题。
额外写个脚本再验证下,我们 hook
tcp_send_fin
和tcp_fin
这两个函数,我们预期的结果是,有一次内核状态为TCP_FIN_WAIT1
的 FIN 发送请求(位于tcp_send_fin
),没有TCP_FIN_WAIT2
的tcp_fin
的处理(收到 FIN 后的处理)可以用上面的最小复现的例子试一下