非阻塞套接字
在阻塞模式中,我们会一直等待客户端成功连接到或者消息成功接收到
而在非阻塞模式下,我们不会去等到一个客户端连接就可以继续代码里面下面的语句
但是也可能会因为我们非阻塞直接向下运行程序: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) # 设置端口复用