python-基于UDP通信的套接字,socketserver模块的使用
一、基于UDP协议通信的套接字
udp是没有链接的,所以先启动哪一端都不会报错
import socket server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) server.bind(('127.0.0.1',8082)) while True: data,client_addr=server.recvfrom(1024) print(data) server.sendto(data.upper(),client_addr) server.close()
import socket client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True: msg=input('>>: ').strip() client.sendto(msg.encode('utf-8'),('127.0.0.1',8082)) data,server_addr=client.recvfrom(1024) print(data)
由于udp无连接,所以可以同时多个客户端去跟服务端通信(实现简单的并发,并不可靠)
import socket client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True: msg=input('>>: ').strip() client.sendto(msg.encode('utf-8'),('127.0.0.1',8082)) data,server_addr=client.recvfrom(1024) print(data)
udp不会出现粘包现象,因为每个中就已经有了报头,这样对于接收端来说,容易区分处理。
udp的recvfrom是阻塞的,一个recvfrom(x)必须对唯一一个sendinto(y),收完了x个字节的数据就算完成,若是y>x数据就丢失,这意味着udp根本不会粘包,但是会丢数据,不可靠
二、socketserver模块
socketserver模块简化了编写网络服务程序的任务,是python标准库中很多服务器框架的基础。
socketserver中包含了两种类,一种为服务类(server class),一种为请求处理类(request handle class),前者主要做的是建立链接的过程,后者注重用户数据的处理
要实现一项服务,还必须派生一个handler class请求处理类,并重写父类的handle()方法。handle方法就是用来专门是处理请求的。该模块是通过服务类和请求处理类组合来处理请求的。SocketServer模块提供的请求处理类有BaseRequestHandler。
1.基于tcp协议通信
# 服务端必须满足至少三点: # 1. 绑定一个固定的ip和port # 2. 一直对外提供服务,稳定运行 # 3. 能够支持并发 import socketserver # 自定义类用来处理通信循环 class MyTCPhanler(socketserver.BaseRequestHandler): def handle(self): while True: try: data = self.request.recv(1024) if len(data) == 0: break # 针对linux系统 print('-->收到客户端的消息: ', data) self.request.send(data.upper()) except ConnectionResetError: break self.request.close() if __name__ == '__main__': server=socketserver.ThreadingTCPServer(('127.0.0.1',8081),MyTCPhanler) server.serve_forever() # 链接循环
from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(('127.0.0.1', 8081)) # 通信循环 while True: # msg=input('>>: ').strip() #msg='' # if len(msg) == 0:continue # client.send(msg.encode('utf-8')) #client.send(b'') client.send('hello'.encode('utf-8')) #client.send(b'') # print('has send') data=client.recv(1024) # print('has recv') print(data) client.close()
from socket import * client = socket(AF_INET, SOCK_STREAM) client.connect(('127.0.0.1', 8081)) # 通信循环 while True: # msg=input('>>: ').strip() #msg='' # if len(msg) == 0:continue # client.send(msg.encode('utf-8')) #client.send(b'') client.send('hello'.encode('utf-8')) #client.send(b'') # print('has send') data=client.recv(1024) # print('has recv') print(data) client.close()
2.基于udp协议通信
import socketserver class MyUdphandler(socketserver.BaseRequestHandler): def handle(self): data,sock=self.request sock.sendto(data.upper(),self.client_address) if __name__ == '__main__': server=socketserver.ThreadingUDPServer(('127.0.0.1',8081),MyUdphandler) server.serve_forever()
from socket import * client=socket(AF_INET,SOCK_DGRAM) while True: client.sendto(b'hello',('127.0.0.1',8081)) data,server_addr=client.recvfrom(1024) print(data)
from socket import * client=socket(AF_INET,SOCK_DGRAM) while True: client.sendto(b'hello',('127.0.0.1',8081)) data,server_addr=client.recvfrom(1024) print(data)
焚膏油以继晷,恒兀兀以穷年。