UDP协议
UDP协议,即用户数据报协议(User Datagram Protocol),是一个简单的面向数据报的传输层协议。UDP协议只在IP数据报服务商增加了很少一点的功能,就是复用和分用,以及差错检测的功能。
基于UDP协议的Socket
1.udp协议客户端允许发空
2.udp协议不会粘包
3.udp协议服务端不存在的情况下,客户端照样不会报错
4.udp协议支持并发
UDP叫数据报协议,意味着发消息都带有数据报头
UDP的server不需要就行监听也不需要建立连接
在启动服务之后只能被动的等待客户端发送消息过来,客户端发送消息的时候,要带上服务端的地址
服务端在回复消息的时候,也需要带上客户端的地址
1.服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
msg, addr = server.recvfrom(1024)
print(msg.decode('utf-8'))
server.sendto(b'hello', addr)
server.close()
2.客户端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)
client.sendto(b'hello baby!', server_addr)
msg, addr = client.recvfrom(1024)
print(msg, addr)
udp特点:
无链接,类似于发短信,发了就行对方爱回不回,没有任何关系。将服务端关了,客户端起起来照样能够发数据。因为不需要考虑服务端能不能收到
验证udp协议有无粘包问题
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
print(server.recvfrom(1024))
print(server.recvfrom(1024))
print(server.recvfrom(1024))
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1',8080)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)
client.sendto(b'hello',server_addr)
基于UDP实现简易版本的qq
1.服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
while True:
msg, addr = server.recvfrom(1024)
print(addr)
print(msg.decode('utf-8'))
info = input('>>>:').encode('utf-8')
server.sendto(info, addr)
server.close()
2.客户端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)
while True:
info = input('>>>:')
info = ('来自客户端1的消息:%s'%info).encode('utf-8') # 改中文备注即可
client.sendto(info, server_addr)
msg, addr = client.recvfrom(1024)
print(msg.decode('utf-8'), addr)
client.close()
总结:
TCP协议就类似于打电话
UDP协议就类似于发短信
SocketServer模块介绍(让tcp也能支持并发)
socketserver是一个socket的服务器模块的使用,在这个模块中,主要也就是实现服务器类的相关功能,在其中,也就是将socket模块和select模块进行了封装,从而创建了一些基类供人使用。
TCP socketserver使用
import socketserver
class MyTcpServer(socketserver.BaseRequestHandler):
def handle(self):
while True:
try:
data = self.request.recv(1024) # 对于tcp,self.request相当于conn对象
if len(data) == 0:break
print(data)
self.request.send(data.upper())
except ConnectionResetError:
break
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1',8081),MyTcpServer)
server.serve_forever()
UDP socketserver使用
import socketserver
class MyUdpServer(socketserver.BaseRequestHandler):
def handle(self):
while True:
data, sock = self.request
print(data)
sock.sendto(data.upper(), self.client_address)
if __name__ == '__main__':
server = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyUdpServer)
server.serve_forever()
首先定义了一个类,也就是处理请求的类,从基类baserequesthandler继承,主要就是重写其中handle方法,告知服务器如何来处理客户端的请求。然后创建了一个线程的TCP服务器类,也就是通过多线程来进行应答客户端,然后使用一直运行的方法也就是serve_forever。