1、最大半连接数
什么是最大半连接数
半连接:在进行TCP
协议通信时,客户端与服务器端进行三次握手建立连接,但是有时客户端与服务器端进行了连接申请,服务器端也同意了申请(既已经完成三次握手的两次),此时只需要客户端再次进行确认即可建立连接,但是此时客户端未进行确认,就会进入半连接状态
最大半连接数:三次握手没有完全执行完毕的连接的最大数量
为什么需要最大半连接数?
在根据TCP
协议进行网络通讯时,会进行三次握手建连接,四次挥手断连接,但是有时当连接服务端的客户端较多时,会大量占用服务器端的资源,容易导致服务端奔溃,此时需要对连接的数量进行限制,只有在规定的数量之内才能与服务端进三次握手建连接,超过数量连接的申请会直接被驳回,不能建立连接。
如何使用最大半连接数?
当我们创建了socket
对象后,使用`socket.listen()
方法时可以设置最大半连接数的数值
2、粘包问题
什么是粘包问题?
当我们使用TCP
流式协议进行socket
对象的创建时,由于操作系统的优化机制,会将时间 间隔较短且数据量较小的数据合并成一次发送,而由于流式协议的特点,在发送数据时是没有数据的边界的,这时如果发送时时间间隔较短且数据量较小时,两次数据就会粘包,或者是在取值时,没有完全取出发送的数据,那么剩余的数据就会在第二次取值时被取出,影响数据的完整性,这种不能将两次数据进行分开的问题就是粘包问题
为什么会有粘包问题?
因为在流式协议中,数据之间是没有边界的,如果将两个数据放到一起,那么这两个数据就不能分开谁是谁,这种不能将数据分开的问题叫做粘包问题
只有流式协议才有粘包问题,既只有TCP
协议有粘包问题,UDP
是没有粘包问题的,因为UDP
是数据报协议,在使用UDP
发送信息时,会自动加上报头及报尾,这样数据之间就有了边界,每次取值就可以将每次的值完全取出,不存在粘包问题
如何处理粘包问题?
要解决粘包问题的方案有两种:
1、扩大两次发送时间,这种方法可以解决两次发送时间太短导致的粘包问题,但是,对于不能一次取出全部数据的问题,这种方法就不能解决
2、对数据进行分组,为数据添加报头,每次只去一次发送的值,这样就可以从根本上解决存在的粘包问题
那么如何对数据添加报头呢
我们可以这样操作,在发送数据之前,先将数据的长度进行发送,然后在进行数据的发送,但是数据的长度也可能不是固定长度的,这样还是不能解决问题,有没有一种方法,可以将数值类型的数据转换成固定长度的数据呢?
通过struct模块可以将数值类型的数据装换成固定长度的二进制字符串
使用方法为:
impotr struct
struct.pack("类型",要转换的数值)
使用上述方法可以将数值转换成固定长度的二进制字符串
同样在接收方可以使用
import struct
struct.unpack("类型",要转换的二进制字符串)
这样通过将数据的长度进行转换,转换成固定长度的字符串,这样首先发送这个字符串,再将实际的数据发送,在接收方首先通过接受固定长度的字符串,从中将信息的长度转换出来,这样在下次接收时就可以将整个数据接收出来,如果数据的长度过长,这样就可以使用while循环进行循环接收,判断已接收数据与总数据长度,进而将整个数据接收
我们这样解决了粘包问题,但是如果我们想获得数据的格式,文件名等消息时应该怎么办呢?
这样可以首先将需要首先发送过去的数据进行组合,组合成一个字典类型,在转换成json
字符串,得到这个json
字符串的长度,在将这个长度转换成固定长度的struct
类型,在进行发送时,首先将固定长度的字符串首先发送,再根据得到的数字接收报头,在将报头转换成字典类型,在从中取出需要的值(如文件名、文件的大小,文件的类型等)再根据得到的文件大小循环接收发送方发送的数据,直至数据完全取出。