原理和我那篇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()