Python非阻塞套接字&端口复用

5 阅读2分钟

非阻塞套接字

在阻塞模式中,我们会一直等待客户端成功连接到或者消息成功接收到

而在非阻塞模式下,我们不会去等到一个客户端连接就可以继续代码里面下面的语句

但是也可能会因为我们非阻塞直接向下运行程序:TCP模型下可能因为客户端还没有连接到就去获取对应数据;UDP模型则会将直接就去接收别人发来的消息,并认为消息有效。但是可能现在没有任何一个人发送消息。这些情况都会导致我们的程序抛出异常。所以需要我们对非阻塞套接字进行合理的异常捕获处理

s.setblocking(1)

使用s.setblocking(0)将套接字设置为非阻塞模式

非阻塞模式下,常出现的错误是BlockingIOError,只需要进行简单的异常捕获即可

try:
	c,addr = s.accept() # 阻塞等待客户端连接
except BlockingIOError as e:
	pass
else:
	c.setblocking(0) # 设置客户端套接字非阻塞模式
	while True: # 循环处理客户端事务

端口复用

在关闭了服务端程序之后又在短时间内继续开启,那么代码可能会抛出如下异常

Traceback (most recent call last):
	File "tcpServer.py", line 4, in <module>
		s.bind( ('',8080) ) # 绑定IP端口
OSError: [Errno 98] Address already in use

因为没有显示的关闭套接字,那么短时间内使用这个端口,会因为端口处于释放状态或者还在为上一个程序工作而抛出Address already in use这样的错误

而为套接字设置端口复用,是为了让程序重启时,之前占用的端口可以立即被绑定使用,而不是出现地址被使用而绑定失败,那只能等待一会儿,才能使用它(一般需要花费两分多钟)

设置了套接字端口复用之后,我们可以立即使用它,会明显缩短等待时间,下一次这个端口的套接字不需要等待TIME_WAI断开时间也可以立即使用

同时设置套接字端口复用,还有一个重要的意义在于它在下一次使用时将上一次程序所残留的TCP数据包清除,这样也避免了下一次绑定了相同地址而获取到之前的残留数据,而导致发生不可预估的错误

  • 端口复用主要目的
    • 保证TCP连接可靠关闭
    • 为每次使用清除残留TCP数据
    • 缩小套接字地址使用等待时间
  • 设置端口复用
import socket # 导入必须模块socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 创建套接字

s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 设置端口复用