Python网络编程UDP协议概述及UDP协议多人聊天室模型

UDP协议概述

  • UDP协议——User Datagram Protocol,即用户数据包协议,UDP协议是无连接、不可靠、高效率数据传输协议。
  • UDP协议优点:开销小、速度快、无连接。
  • UDP协议缺点:无确认重传和排序、无流控制、无错误恢复。
  • UDP协议是面向报文的传输协议,它对报文既不拆分也不合并,而是给报文添加头部后就向下交给IP层。发现错误时不要重传,只是简单地把错误的报文扔掉、或给应用程序提供警告。
  • UDP协议广泛运用在强调数据传输速率的多媒体应用领域,例如网络聊天、在线视频、网络游戏、实时监控、路由协议中修改路由表等。
    • TCP协议遇到丢包或错误时要求重传,因而导致传输速率大幅降低。
    • UDP协议遇到丢包或错误时不要求重传,因为一个报文丢失后几秒内会有新的报文替代它,所以UDP协议传输速率比TCP协议高很多。
    • 应用程序需要根据需要自定义应用层协议来处理报文丢失、错误、失序的情况。
  • 编写UDP应用程序需要审慎考虑合适的报文长度:
    • 局域网最大传输单元(Maximum Transmission Unit,MTU)默认是1500字节。
    • UDP协议头部是8字节、IP层协议头部是20字节。
    • 单条报文建议长度是1024字节,最大长度不得超过65507字节(报文加头部总长不得超过65535字节)。
    • 网络环境较好时报文长度及接收缓存建议设大一些,可以减少报文接收不及时导致丢包的概率。

udp协议服务端

  1. 创建socket实例。

    sk = socket.socket(type=socket.SOCK_DGRAM) 
    

    注意:type=socket.SOCK_DGRAM是指定关键字参数,不能“缺省type=”,该参数用来指定使用udp协议。

  2. 绑定ip和端口。

    sk.bind(('127.0.0.1',9001))
    

    说明:该方法有一个参数,类型是元组(元组的第一个元素是IP,第二个元素是端口)。无返回值。

  3. 从UDP客户端收报文。

    message,addrress = sk.recvfrom(1024)
    

    说明:该方法参数是接收消息长度。返回值是元组,元组第一项是消息,第二项是ip及端口。

  4. 发送报文给UDP客户端。

    sk.sendto(message,address)
    

    说明:该方法有二个参数,第一个参数是要发送的消息,必须是bytes型;第二个参数是元组(元组的第一个元素是IP,第二个元素是端口)。返回值是发送的字节数。

udp协议客户端

  1. 创建socket实例。

    sk = socket.socket() 
    
  2. 发报文给UDP服务端。

    sk.sendto(message.encode(),('127.0.0.1',9001))
    

    说明:该方法有二个参数,第一个参数是要发送的消息,必须是bytes型;第二个参数是元组(元组的第一个元素是IP,第二个元素是端口)。返回值是发送的字节数。

  3. 从UDP服务端收报文。

    message = sk.recv(1024).decode()
    

    说明:该方法参数是接收消息长度。返回值是消息。

案例:udp协议聊天室

  • 服务端

    import socket
    
    HOST = '127.0.0.1'  # IP地址
    PORT = 50007  # 端口
    max_connect = 5
    
    
    def main():
        accounts = {}
        with socket.socket(type=socket.SOCK_DGRAM) as sk:
            sk.bind((HOST, PORT))
            while True:
                msg, address = sk.recvfrom(1024)
                rev = msg.decode().split('|||')
                accounts[rev[0]] = address
                if rev[1] in accounts:
                    sk.sendto(msg, accounts[rev[1]])
    
    
    if __name__ == "__main__":
        main()
    

    说明:这个是UDP协议简易聊天室服务端模型,服务端接收到客户端发来的消息,会记录客户端的ip和端口以及账号,并更新到字典中。遇到发往目标账户的消息在字典中时,会将信息转发给目标账户,从而实现多人聊天功能。
    注意:代码目前没有缓存消息,当要发送的目标不在线时,该消息会被丢弃。

  • 客户端

    import socket
    from threading import Thread
    import sys
    
    HOST = '127.0.0.1'  # IP地址
    PORT = 50007  # 端口
    
    
    class Transceiver:
        def __init__(self, conn, server, account: str, target: str, buffer: int = 1024) -> None:
            self.conn = conn  # socket实例
            self.server = server  # 目标ip及端口
            self.buffer = buffer  # 缓存区大小
            self.path = (account + '|||' + target + '|||').encode()  # 己方账号
    
        def send(self, message: str) -> None:
            """发送消息"""
            if type(message) is str:  # 判断消息类型
                message = message.encode()  # 将消息转成bytes型,缺省参数是utf8编码
            self.conn.sendto(self.path + message, self.server)  # 发送消息
    
        def recv(self):
            """接收消息"""
            message, _ = self.conn.recvfrom(self.buffer)
            message = message.decode('utf8').split('|||')
            return message[1], message[2]  # 返回消息字符串
    
    
    def main():
        def send(m, message):
            m.send(message)
    
        def recv(m):
            while True:
                try:
                    source, data = m.recv()
                    print(f'收到"{source}"发来的信息:{data}')
                except:
                    pass
    
        with socket.socket(type=socket.SOCK_DGRAM) as sk:
            account = input("请输入你的账号:")
            target = input("请输入你想聊天的账号:")
            m = Transceiver(sk, (HOST, PORT), account, target)
            t = Thread(target=recv, args=(m,))
            t.setDaemon(True)
            t.start()
            while True:
                message = input('请输入你要发送的信息:')
                if not message:
                    continue
                if message == 'q' or message == 'Q':
                    sys.exit(0)
                Thread(target=send, args=(m, message)).start()
    
    
    if __name__ == "__main__":
        main()
    
    

    说明:这个是udp协议简易聊天室客户端模型,客户端登录时首先输入自己的账号和对方的账号,然后进入循环,循环输入发给对方账号的消息,另开了子收获进程接受服务端转发来的消息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值