(一)TCP十种状态数据库
上一篇咱们学习了tcp三次握手和四次挥手的过程,其中设计到的状态一共有10种,即为下图所示:后端
(二)TCP的2MSL问题服务器
2MSL即两倍的MSL,MSL即为数据包在传输过程当中能够存活的最长时间,TCP的TIME_WAIT状态也称为2MSL等待状态:当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次握手完成后发送了第四次握手的ACK包后就进入了TIME_WAIT状态,其必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个 ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后能够再发一个ACK应答包。并发
在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。app
当链接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。socket
不过在实际应用中能够经过设置 SO_REUSEADDR选项达到没必要等待2MSL时间结束再使用此端口。tcp
(三)TCP的长短链接学习
模拟一种TCP短链接的状况:网站
在步骤5中,通常都是 client 先发起 close 操做。固然也不排除有特殊的状况。spa
从上面的描述看,短链接通常只会在 client/server 间传递一次读写操做!
再模拟一种长链接的状况:
长链接能够省去较多的TCP创建和关闭的操做,减小浪费,节约时间。
对于频繁请求资源的客户来讲,较适用长链接。
client与server之间的链接若是一直不关闭的话,会存在一个问题:
随着客户端链接愈来愈多,server迟早有扛不住的时候,这时候server端须要采起一些策略,如关闭一些长时间没有读写事件发生的链接,这样能够避免一些恶意链接致使server端服务受损;若是条件再容许就能够以客户端机器为颗粒度,限制每一个客户端的最大长链接数,这样能够彻底避免某个蛋疼的客户端连累后端服务。
长链接多用于操做频繁,点对点的通信,并且链接数不能太多状况。
每一个TCP链接都须要三次握手,这须要时间,若是每一个操做都是先链接,再操做的话那么处理速度会下降不少,因此每一个操做完后都不断开,再次处理时直接发送数据包就OK了,不用创建TCP链接。
例如:数据库的链接用长链接,若是用短链接频繁的通讯会形成socket错误,并且频繁的socket 建立也是对资源的浪费。
而像WEB网站的http服务通常都用短连接,由于长链接对于服务端来讲会耗费必定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的链接用短链接会更省一些资源,若是用长链接,并且同时有成千上万的用户,若是每一个用户都占用一个链接的话,那可想而知吧。因此并发量大,但每一个用户无需频繁操做状况下需用短连好。
(四)listen的队列长度
服务器端:
1 from socket import * 2 from time import sleep 3 4 # 建立socket 5 tcpSerSocket = socket(AF_INET, SOCK_STREAM) 6 7 # 绑定本地信息 8 address = ('', 7788) 9 tcpSerSocket.bind(address) 10 11 connNum = int(raw_input("请输入要最大的连接数:")) 12 13 # 使用socket建立的套接字默认的属性是主动的,使用listen将其变为被动的,这样就能够接收别人的连接了 14 tcpSerSocket.listen(connNum) 15 16 while True: 17 18 # 若是有新的客户端来连接服务器,那么就产生一个新的套接字专门为这个客户端服务器 19 newSocket, clientAddr = tcpSerSocket.accept() 20 print clientAddr 21 sleep(1)
客户端:
1 from socket import * 2 3 connNum = raw_input("请输入要连接服务器的次数:") 4 for i in range(int(connNum)): 5 s = socket(AF_INET, SOCK_STREAM) 6 s.connect(("192.168.1.102", 7788)) 7 print(i)