基于UDP协议的socket套接字编程
一、UDP套接字简单示例
- UDP不需要经过3次握手和4次挥手,不需要提前建立连接直接发数据就行。所以是无连接的,UDP的sendto不用管是否有一个正在运行的服务端,可以己端一个劲发消息,只不过数据丢失。先启动哪一端都不会报错
- recvfrom收的数据小于sendto发送的数据时,在mac和linux系统上会数据直接丢失,在window系统上发送的比接收的大直接报错。
- 只有sendto发送数据,没有recvfrom接收数据,数据丢失。
- UDP协议是数据报协议,发空的时候也会自带报头,因此客户端输入空,服务端也能收到
客户端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_address = ('127.0.0.1',8080) # 获取服务端的地址
# 循环打印数据
while True:
client.sendto(b'hello',server_address) # 使用地址发送数据
data,addr = client.recvfrom(1024) # 接收数据
print('服务端发来的数据',data) # 打印数据
print('服务端的地址',addr) # 打印地址
服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080)) # 自己的地址
while True:
data,addr = server.recvfrom(1024) # 接收客户端的数据和地址
print('数据',data) # 打印数据
print('地址',addr) # 打印地址
server.sendto(data.upper(),addr) # 将数据转化成大写发送出去
二、UDP套接字无粘包问题
- UDP协议一般不用于传输大数据
- UDP套接字虽然没有粘包问题,但是不能替代TCP套接字,因为UDP协议有一个缺陷:如果数据发送的途中,数据丢失,则数据就没了,而TCP协议则不会有这种缺陷,因此一般UDP套接字用户无关紧要的数据发送,例如qq聊天。
服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
data,addr = server.recvfrom(1024)
print(data)
data,addr1 = server.recvfrom(1024)
print(data)
data,addr2 = server.recvfrom(1024)
print(data)
客户端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_address = ('127.0.0.1',8080)
client.sendto(b'hello',server_address)
client.sendto(b'hello',server_address)
client.sendto(b'hello',server_address)
三、QQ聊天
- 由于UDP无连接,所以可以同时多个客户端去跟服务端通信。
服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
while True:
data,addr = server.recvfrom(1024)
print(data.decode('utf-8'))
msg = input('>>>')
server.sendto(msg.encode('utf-8'),addr)
客户端1
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
while True:
data,addr = server.recvfrom(1024)
print(data.decode('utf-8'))
msg = input('>>>')
server.sendto(msg.encode('utf-8'),addr)
客户端2
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_address = ('127.0.0.1',8080)
while True:
msg = input('>>>:')
msg = f'来自客户端2的消息:{msg}'
client.sendto(msg.encode('utf-8'),server_address)
data,server_addr = client.recvfrom(1024)
print(data.decode('utf-8'))
总结
UDP通信协议是数据报协议(自带报头),没有双向通道,通信类似于发短信。UDP类似于发短信,TCP类似于打电话。
并发:看上去像同时运行的。
并行:真正意义上的同时运行
- UDP协议客户端允许发空
- UDP协议不会产生粘包
- UDP协议服务端不存在的情况下,客户端照样不会报错
- UDP协议支持并发