这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
由于不可言的原因,完整项目代码放在
paste.ubuntu.com/p/sMyvMvfHW… 服务端首先调用MyRequestHandle的handle方法
s = socketserver.ThreadingTCPServer(('127.0.0.1', 8888), MyRequestHandle)
while True 接收来自客户端的请求,调用get_request方法来获取完整的请求信息, 包括请求头和请求体。 在get_request方法中,首先接收一下请求头,如下
res_head = self._receive_exact_bytes(conn, MsgConstants.HEAD_SIZE, MsgConstants.HEAD_SIZE)
接收到请求头后,解码请求头,获取请求体的长度,
head = MsgHeader()
head.decode(res_head)
在知道了请求体长度后,就可以调用_receive_exact_bytes方法,来获取准确长度的数据,来完整的获取到数据。
接下来讲解一下_receive_exact_bytes方法。
def _receive_exact_bytes(self, conn, expected_size, buf_size):
expected_size 是期待得到的数据长度,buf_size是每次接收的数据长度,数据过大的话,如果一次性接收,会超时,或者引起其它问题,所以要和客户端约定好一个buf_size, 客户端要发过来的数据过大的时候,按照这个长度切片,分次发送到服务端,服务端在拿到请求头的时候,就已经知道请求体有多长了,所以在recv_len < expected_size的时候,就会继续接收来自客户端的数据,直到拿到所有数据。
在代码里是这样的
while recv_len < expected_size:
remain = expected_size - recv_len
hd = conn.recv(min(remain, buf_size))
循环获取到所有数据后返回,至此已经拿到了完整的请求头, 然后就可以做一些例如对数据库中数据,增删改查,登录,退出登录等操作,并且有操作的结果要发送回给客户端。
如果是查询的话,有可能数据量也比较大,大于我们约定的buf_size的时候,也需要切片,分次发送给客户端,见send_response方法。
response_head = MsgHeader(615, len(db_result))
conn.send(response_head.encode()) # 3、发送报头
for i in range(len(db_result) // 2048 + 1):
tmp_result = db_result[i * 2048:(i + 1) * 2048]
conn.send(tmp_result) # 4、发送真实的数据
首先创建一个请求头,encode()请求头,先把请求头发给客户端, 然后对db_result进行切片,分次用conn.send发送给客户端。
客户端接收到数据后,展示在Qt上,以供用户使用。
下一篇简单讲解一下对应的python测试客户端开发。