UDP服务器端
import threading import socket class Server: # 初始化:绑定端口 def __init__(self, ip=‘127.0.0.1‘, port=9000): self.socket_instance = socket.socket(type=socket.SOCK_DGRAM) self.addr = (ip, port) self.event = threading.Event() self.clients = set() self.__run() def __run(self): # 绑定地址,监听地址 self.socket_instance.bind(self.addr) # 将阻塞的__recvfrom()方法放到线程执行 threading.Thread(target=self.__recvfrom, name=‘recvfrom‘).start() def __recvfrom(self): while not self.event.is_set(): try: # 这里捕获异常是由于一旦关闭socket,那么data, addr不会获取到值,那么应该捕获异常,给data, addr赋值 data, addr = self.socket_instance.recvfrom(1024) data = data.decode().strip() print(data) except Exception as e: data = ‘quit‘ addr = ‘None‘ # 拿到心跳信息 if data == ‘@#!%%^SDF@‘: self.clients.add(addr) continue # 拿到数据, 如果是quit if data == ‘quit‘: if addr in self.clients: self.clients.remove(addr) # 这里continue的原因是,udp不需要与客户端建立连接,每次请求来了以后,可以直接拿到客户端发送的数据 # 不是break continue self.clients.add(addr) threading.Thread(target=self.__send,args=(data, ), name=‘send‘).start() def __send(self, data): for addr in self.clients: self.socket_instance.sendto(‘Robby收到{}\n‘.format(data).encode(), addr) def stop(self): self.clients.clear() self.event.set() self.event.wait(3) self.socket_instance.close() print(‘UDP服务器停止‘) raise SystemExit(0) if __name__ == ‘__main__‘: # 1: 启动服务器端 chatServer = Server() # 2:用户可以输入quit暂停服务器 while True: cmd = input(‘请输入命令: ‘).strip() chatServer.stop() if cmd == ‘quit‘ else print(‘可以输入quit暂停服务器端‘)
UDP客户端
import threading import socket class Client: def __init__(self, ip=‘127.0.0.1‘, port=9000, interval=5): self.socket_instance = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) self.addr = (ip, port) self.event = threading.Event() self.interval = interval self.__run() def __sendHeartBeat(self): while not self.event.wait(5): # 客户端发送的心跳包,服务器端不会回包 self.socket_instance.sendto(‘@#!%%^SDF@‘.encode(), self.addr) def __recvfrom(self): while not self.event.is_set(): try: data, addr = self.socket_instance.recvfrom(1024) print(addr) print(data.decode()) except Exception as e: print(e) def __serverQuit(self): self.socket_instance.sendto(‘quit‘.encode(), self.addr) def send(self, data:str): self.socket_instance.sendto(data.encode(), self.addr) def __run(self): # 启动一个线程,发送心跳包 threading.Thread(target=self.__sendHeartBeat, daemon=True).start() # 启动一个线程,接收数据 threading.Thread(target=self.__recvfrom, ).start() def stop(self): self.__serverQuit() self.event.set() self.event.wait(3) self.socket_instance.close() print(‘UDP客户端停止‘) raise SystemExit(0) if __name__ == ‘__main__‘: # 1:启动客户端 client = Client() # 客户端可以像服务器端发送数据 while True: cmd = input(‘请输入内容:‘).strip() client.stop() if cmd == ‘quit‘ else client.send(cmd)
TCP传输数据使用字节流的方式传输,而UDP是数据报传输;
TCP对网络条件要求高,而UDP更适合实时传输;
TCP编程可以保证传输的可靠性,UDP则不保证;
TCP会产生粘包现象,而UDP则容易丢包;
TCP使用listen方法和accpet方法,而UDP不需要;
TCP使用recv方法和send方法,而UDP使用recvfrom方法和sendto方法;
创建 socket 对象;
向socket 对象绑定服务器地址;
进入与客户端交互数据的循环阶段;
接收客户端发来的数据(包括 bytes 对象 data,以及客户端的 IP 地址和端口号 addr,其中 addr 为二元组 (host, port);
打印接收信息,表示从地址为 addr 的客户端接收到数据);
关闭;
创建 socket 对象;
初始化 UDP 服务器的地址;
进入与服务器交互数据的循环阶段;
等待用户输入数据;
向服务器端发送接收数据;
关闭套接字,不再向服务器发送数据;
原文:https://www.cnblogs.com/zhongguiyao/p/14874333.html