UDP通讯协议

与TCP相同的是 客户端也不需要bind一个固定端口 让系统随机分一个



UDP和TCP异同处

UDP在使用时
1.修改socket的参数 第一个任然是AF_INET 第二个需要换成AOCK_DGRAM
2.UDP 不需要建立连接 所以没有三次握手和四次挥手




相同点:
服务器:都需要绑定端口和ip
recv与recvfrom都是阻塞的



不同点:
服务器:不需要监听和接受请求
TCP服务器默认只能与一个客户端进行通讯 下一个客户端必须等待上一个断开连接才能被处理
UDP多个客户端的请求会被一次处理 由于不需要建立连接 所以给你感觉时好像可以同时处理

客户端:不需要建立连接 直接发送即可
可以发送空消息


在UDP中 无论是客户端还是服务器 接受:recvfrom 发送:sendto
UDP是基于数据报的协议
发送和接收都是以数据报为单位
而TCP得单位是字节


接收方的缓冲区大小即使大于发送方发送的数据长度 也不会沾包

当接受方缓冲区的长度小于数据报的长度 windows会报异常 而Linux不会 缓冲区有多大就收几个

注意:UDP在使用时,必须保证收到的缓冲区大小 大于或等于发送的数据
由于缓冲区大小不可能无限大 所以UDP不适用于数据量较大的情况下 如果一定要使用UDP来传输大量数据的话
需要自己来对数据进行切割和组装

udp最大的数据报 受数据帧大小限制 最大为1472字节

TCP发送数据后 不会立即删除缓存数据 需要等到对方确认信息到达

结论:当数据量较大时 需要TCP
import socket
c=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)


addr=('127.0.0.1',8808)
c.sendto('hello 我是udp客户端'.encode(),addr)
print('over')



data,addr=c.recvfrom(1024)
print(data.decode(),addr)
客户端
import socket



s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(('127.0.0.1',8808))




while True:
    data,addr=s.recvfrom(1024)
    s.sendto(data.upper(),addr)
    print(data)
服务器


自定义报头
发送端:
1.先将所有的额外信息打包到一个头中
2.然后先发送头部数据
3.最后发送真实数据

接收端:
1.接收固定长度的头部长度数据
2.根据长度数据获取头部数据
3.根据头部数据获取真实数据
import struct

def send_msg(data,c):
    # 发数据
    data = data.encode("utf-8")
    len_bytes = struct.pack("q",len(data))
    c.send(len_bytes)
    c.send(data)

def recv_msg(sock):
    # 接收响应
    length = struct.unpack("q",sock.recv(8))[0]


    # 已接收长度
    c_size = 0

    # 存储总数据
    data = b""
    while c_size < length:
        res = sock.recv(1024)
        if not res:
            break
        c_size += len(res)
        data += res # 拼接数据

    # 长度符合则接收成功
    if length == c_size:
        print("接收成功")

    return data.decode("utf-8")
tool
import socket
import tool

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(("127.0.0.1",8989)) # 0 - 1023 > 可用端口 <  65535

s.listen() # 最大的半连接数量限制

while True:
    c,addr = s.accept()

    while True:
        try:
            # 从操作系统缓冲区读取1024到应用程序
            data = tool.recv_msg(c)  # 阻塞函数   等到操作系统缓冲区有数据为止
            if not data: # 对方正常下线 ,,linux对方异常断开连接
                c.close()
                break

            print(data)

            # 返回数据
            tool.send_msg(data.upper(),c)
        except Exception as e: # 抛出异常仅在windows下 对方异常下线才会发生
            print(e)
            c.close()
            break
服务器
import socket
import tool
c = socket.socket()

c.connect(("127.0.0.1",8989)) # 就在执行三次握


while True:
    msg = input(">>>:")
    if not msg:
        continue
    tool.send_msg(msg,c) # 发送

    res = tool.recv_msg(c) # 接收
    print(res)
客户端

猜你喜欢

转载自www.cnblogs.com/gengbinjia/p/10471544.html