python之socket编程(TCP)-解决粘包拆包 作者:马育民 • 2018-12-28 11:07 • 阅读:10592 # 概述 从 [TCP粘包和拆包](http://www.malaoshi.top/show_1EF2UqhwMPPZ.html "TCP粘包和拆包") 文中可知,解决粘包拆包有若干种方法,我们目前要实现的socket通信,建立连接后,发送的数据量不大,发送数据后断开连接,此时采用下面这种方法最为合理: 在消息的尾部加一些特殊字符(比如换行符),那么在读取数据的时候,只要读到这个特殊字符,就认为是一个完整的数据包了 这种方式编程简单更加合理。 # 客户端改动 在发送文本的后面加上特殊的结束符号```\n```,注意:文本中不能再有符号```\n```,否则会造成歧义,代码如下: ``` #coding=utf-8 import socket s = socket.socket() s.connect(('127.0.0.1', 9999)) data=s.recv(1024) print('来自server的消息:',data.decode('utf-8')) s.sendall('name:lilei\n'.encode('utf-8')) s.sendall('age:20\n'.encode('utf-8')) s.sendall('gender:male\n'.encode('utf-8')) s.sendall('length:175cm\n'.encode('utf-8')) b='''The Political Bureau of the Communist Party of China Central Committee reviewed on Thursday an intra-Party regulation on political and legal work.The regulation, the first of its kind for the Party, is part of the five-year plan (2018-22) that the CPC Central Committee mapped out in February to have an overall design for the Party's institutional construction.The regulation, as part of the Party's basic laws and regulations, stipulates the Party's leadership over political and legal affairs and translates the Party's long-term successful experience in leading the nation's political and legal work into institutional achievements, according to a statement released after the Thursday meeting.The regulation is also required by upholding and developing socialism with Chinese characteristics as well as modernizing the country's system and capacity for governance, the statement said.The Party strives to have well-established intra-Party regulations and systems in place before the centenary of the Party's founding in 2021 to advance Party-building in the new era.The meeting also highlighted the Party's leadership over political and legal affairs. That exercise of leadership is an important step that aligns the law-based governance of the country with the regulation-based governance of the Party.Xi Jinping, general secretary of the CPC Central Committee, presided over the meeting.The Party's leadership is consistent with the rule of law, as only when the Party's leadership is upheld can people's full democracy be ensured and institutionalized and law-based governance be properly advanced, the statement said.The Party explicitly maintains that judiciary institutions must exercise their power in an independent and fair manner in line with the law, it said, adding that Party organizations and leading officials at various levels must support judiciary institutions' exercise of power.The meeting called for improvement of related systems and mechanisms in implementing the intra-Party regulation, according to the statement.\n'''.encode('utf-8') print('长文的长度:%d'%len(b)) s.sendall(b) s.close() ``` # 服务器端优化 ### 先拼装成大文本,然后处理文本 1. 接收所有数据 2. 将数据解码成字符串 3. 根据结束符将整个字符串拆分 ``` import socket s = socket.socket() s.bind(('0.0.0.0', 9999)) s.listen(5) print('开始监听') #在这里写一个死循环,永远接收客户端请求 while True: conn, address = s.accept() print('接收到客户端请求') print('conn类型',type(conn)) print('address类型',type(address),address) conn.sendall('server is ok!'.encode('utf-8')) last_data=bytes() while True: data=conn.recv(1024) if data: last_data+=data print('接收数据长度:%d'%len(data)) else: break text=last_data.decode('utf-8') lines=text.split('\n') for item in lines: print(item) conn.close() print('-------------------------') ``` **缺点:** 下面 ``` last_data+=data ``` 拼装的方式较慢 ### 将接收到的数据放入list中 上面拼装的方式较慢,采用下面方式继续优化: 1. 接收数据,放入list中 2. 通过```b''.join(l)```获取完整数据 3. 将数据解码成字符串 3. 根据结束符将整个字符串拆分 ``` import socket PORT=9999 s = socket.socket() s.bind(('0.0.0.0', PORT)) s.listen(5) print('开始监听,PORT:',PORT) #在这里写一个死循环,永远接收客户端请求 while True: conn, address = s.accept() print('接收到客户端请求') print('conn类型',type(conn)) print('address类型',type(address),address) conn.sendall('server is ok!'.encode('utf-8')) templist=[] while True: data=conn.recv(1024) if data: templist.append(data) print('接收数据长度:%d'%len(data)) else: break temp=b''.join(templist) text=temp.decode('utf-8') lines=text.split('\n') for item in lines: print(item) conn.close() print('-------------------------') ``` ###接收bytes类型数据直接处理(略) 这个版本是接收bytes类型数据,直接对bytes数据做处理: 1. 找到结束符 2. 然后解码成字符串 ``` import socket s = socket.socket() s.bind(('0.0.0.0', 9999)) s.listen(5) print('开始监听') #在这里写一个死循环,永远接收客户端请求 while True: conn, address = s.accept() print('接收到客户端请求') print('conn类型',type(conn)) print('address类型',type(address),address) conn.sendall('server is ok!'.encode('utf-8')) last_data=bytes() while True: data=conn.recv(1024) #当接收数据长度为0时,表示发送完毕 data_len=len(data) print('接收数据长度:%d'%data_len) if data_len==0: break last_data+=data startpos=0 for index,item in enumerate(last_data): # 将数字转换成字符 if chr(item)=='\n': line=last_data[startpos:index].decode('utf-8') startpos=index+1 print(line) #如果最后一个不是结束符 if last_data[:-1] != '\n': last_data=last_data[startpos:] conn.close() print('\n\n-------------------------') ``` 原文出处:http://www.malaoshi.top/show_1EF2VYAtn26K.html