1、获取socket对象
my_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
AF_UNIX(基于文件的套接字)区别于AF_INET(基于网络的套接字),见
https://www.cnblogs.com/langzou/p/7497848.html
socket.SOCK_STREAM区别于SOCK_DGRAM,两者分别使用TCP和UDP协议
2、阻塞与不阻塞
my_socket.setblocking(0) 0--false,不阻塞。 1--true,阻塞
关于是否阻塞,以recv方法为例(accept、send、recv等方法原理类似):
阻塞:执行recv方法之后,一定要接收到数据才会返回,否则程序就阻塞在这里
不阻塞:执行recv方法之后,如果接收缓冲区里面有消息就接收消息并且返回,如果接收缓冲区里面没有待接收的消息,就会立即抛出异常并返回recv方法。
3、设置等待队列的大小
my_socket_server.listen(5)
5 是最大挂起(等待)连接数,当server正在建立和客户端A的连接的时候,可能客户端B也发起了连接server的请求,但是server目前没空处理这个连接请求,于是将其放在连接等待队列中,待A的连接请求处理完了之后再去队列中取出等待中的B请求,然后处理B请求。注意了,5不是server可接收的最大连接数!
4、开启端口复用
server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 【level,name,value】
socket.SOL_SOCKET,设置项的级别,socket.SOL_SOCKE是socket级别的设置项,该值决定了第二个参数的可选范围。
socket.SO_REUSEADDR端口复用选项
1=打开端口复用选项,0=关闭端口复用选项
虽然允许多个socket绑定在同一个端口上,但是只有最后一个可以正常收发数据。当一个进程结束之后,连
接处于time——waite状态就可以重新再次绑定。而不会报错。
time_waite状态,为什么要有time_waite状态?
主动发关闭方再应答了ACK之后必须等待,确保如果此ACK包丢失之后,被动关闭方再次发送FIN时可以正常
应答,而不是报错。
time_waite2状态,是多长时间?
2MSL (max segment Lifetime:最大分节存活时长)
Windows : MSL = 2 min
linux(Ubuntu, CentOs) : MSL = 60s
Unix : MSL = 30s
为什么是2MSL?
因为每一个网络包在网络中存活的最大时长就是1个msl,2个MSL可以确保之前网络迷途的数据包被正常抛弃
,而不影响后续通信。
举个栗子:
假设ip1:port1和ip2:port2 之间有一个TCP连接。我们关闭了这个链接,如果没有time_waite2,或者小于
2msl的等待时间,过一段时间后在相同IP和端口之间建立了另一个连接。很可能之前连接的迷途包(如果是
fin包)恢复后会传入到新连接中。2MSL的时间足以让这些迷途包被丢弃,而避免相互影响。
如果不开启端口复用影响也不大,主要就是当server程序端口之后,端口处于一个time_waite状态,导致短时间内不能正常启动server,提示端口被占用