基于udp协议的套接字、socketserver模块
一、UDP协议(数据报协议)
1、何为udp协议
不可靠传输,”报头”部分一共只有8个字节,总长度不超过65,535字节,正好放进一个IP数据包。
以太网头 | ip头 | udp头 | 数据 |
2、udp协议的特点
(1)传输数据以数据报的形式传送。因为数据以数据包的形式发送,所以没发送一次就会接收一次
from socket import * server=socket(AF_INET,SOCK_DGRAM) server.bind(('127.0.0.1',8081)) print(server.recvfrom(1024)) print(server.recvfrom(1024)) print(server.recvfrom(1024)) # (b'hello', ('127.0.0.1', 56816)) # (b'world', ('127.0.0.1', 56816)) # (b'sdfas', ('127.0.0.1', 56816))
from socket import * client=socket(AF_INET,SOCK_DGRAM) client.sendto(b'hello',('127.0.0.1',8888)) client.sendto(b'world',('127.0.0.1',8888)) client.sendto(b'sdfas',('127.0.0.1',8888))
(2)客户端只管发送数据,不管服务端给不给回复,所以是一种不可靠的协议
二、基于udp协议的套接字
udp是无链接的,先启动哪一端都不会报错
from socket import * # 1.创建套接字对象 server = socket(AF_INET, SOCK_DGRAM) # 2.绑定服务器IP地址和端口号 server.bind(('127.0.0.1', 8888)) # 3.收发消息 while True: data, cli_addr = server.recvfrom(1024) # 收到的是数据和客户端地址 print(data) server.sendto(data.upper(), cli_addr) # 发送消息,根据客户端地址发送消息 server.close()
from socket import * # 1.创建套接字对象 server = socket(AF_INET, SOCK_DGRAM) # 2.发收消息 while True: client.sendto('hello'.encode('utf-8'), ('127.0.0.1', 8888)) # 根据地址发送消息 data, ser_addr = client.recvfrom(1024) # 收消息,获得服务端的消息和地址 print(data)
三、socketserver模块
1、作用
利用socketserver模块可以实现并发
2、基于TCP协议的并发
自定义类中:
- self.request 即一个套接字对象
- self.client_address 即客户端地址
# 服务端
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
while True: # 通信循环
try:
data = self.request.recv(1024)
print(data.decode('utf-8'))
self.request.send(data.upper())
except ConnectionResetError:
break
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1', 8888), MyTCPHandler)
server.serve_forever() # 链接循环
# 客户端
from socket import *
cli_socket = socket(AF_INET, SOCK_STREAM)
cli_socket.connect(('127.0.0.1', 8888))
while True:
cli_socket.send('hello'.encode('utf-8'))
data = cli_socket.recv(1024)
print(data.decode('utf-8'))
cli_socket.close()
3、基于UDP协议的并发
自定义类中:
- self.request是一个元组(第一个元素是客户端发来的数据,第二部分是服务端的udp套接字对象),如(b'adsf', <socket.socket fd=200, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('127.0.0.1', 8080)>)
- self.client_address即客户端地址
# 服务端 import socketserver class MyUDPHandler(socketserver.BaseRequestHandler): def handle(self): while True: # 通信循环 print(self.request) # (b'hello', <socket.socket fd=216, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('127.0.0.1', 8888)>) data, sock = self.request sock.sendto(data.upper(), self.client_address) if __name__ == '__main__': server = socketserver.ThreadingUDPServer(('127.0.0.1', 8888), MyUDPHandler) server.serve_forever() # 链接循环
#客户端
from socket import *
cli_socket = socket(AF_INET, SOCK_STREAM)
while True:
cli_socket.sendto('hello'.encode('utf-8'), ('127.0.0.1', 8888))
data, server_addr = cli_socket.recvfrom(1024)
print(data.decode('utf-8'))
cli_socket.close()