解决TCP传输黏包的问题(以Python为例)

原理和我那篇C#相同
只是因为Python的编码工具和C#差异挺大的,所以实作细节上不太一样

Server.py

import socketimport threadingimport structclass Server:    def __init__(self, port):        # https://docs.python.org/3.9/library/socket.html        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                # IP设定0.0.0.0的原因可参考这篇        # https://superuser.com/questions/949428/whats-the-difference-between-127-0-0-1-and-0-0-0-0        self.server.bind(('0.0.0.0', port))        self.server.listen(1) # 传入的参数代表允许多少个目标连入                # 因为程式会在等待连线中停住,所以需要使用Thread等非同步方式去处理        self.threadAccept = threading.Thread(target=self.Accept)        self.threadAccept.start()        self.FLAG_RECEIVE = False # 用来控制是否要停止接收资料            def Accept(self):        print('Wait Connect...')        self.socket, self.address = self.server.accept()        print(f'Conneted by {self.address}')                self.server.close() # 若不需要再接收其他连线则可以关掉server这个socket物件                # 準备接收资料        self.FLAG_RECEIVE = True        self.threadReceive = threading.Thread(target=self.Receive)        self.threadReceive.start()            def Receive(self):        while(self.FLAG_RECEIVE):            # 因为Client端分两次传送资料,所以这边也要分两次接收            # unpack详情可看这篇: https://cloud.tencent.com/developer/article/1406350            data = self.socket.recv(4) # int是4byte            msg_len = struct.unpack('i', data)[0] # 解码后是tuple型态,由于只有单个资料,所以这边用[0]            data = self.socket.recv(msg_len)            msg = struct.unpack(str(msg_len)+'s', data)[0] #'同上面的unpack                        print('Receive: ' + msg.decode('utf-8'))                def Close(self):        self.FLAG_RECEIVE = False        self.socket.close()if __name__ == '__main__':    server = Server(8000)    input() # 按下Enter结束程式    server.Close()

Client.py

import socketimport threadingimport structclass Client:    def __init__(self, ip, port):        # https://docs.python.org/3.9/library/socket.html        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        self.socket.connect((ip, port))        self.FLAG_SEND = True        self.thread = threading.Thread(target=self.Send)        self.thread.start()            def Send(self):        while(self.FLAG_SEND):            msg = 'Hello Server!!'.encode('utf-8') # string to byte array            msg_len = int(len(msg)) # 强制转为int类型,大小是4 byte            # 分两次传送,先传递资料数,再传递资料            # pack详情可看这篇: https://cloud.tencent.com/developer/article/1406350            packet_data = struct.pack('i', msg_len) # 将资料封装            self.socket.send(packet_data)            packet_data = struct.pack(str(msg_len)+'s', msg) # 将资料封装            self.socket.send(packet_data)                def Close(self):        self.FLAG_SEND = False        self.socket.close()if __name__ == '__main__':    client = Client('127.0.0.1', 8000)    input() # 按下Enter结束程式    client.Close()

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章