07.网络编程-2.UDP

Posted cjr0707

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了07.网络编程-2.UDP相关的知识,希望对你有一定的参考价值。

1、udp介绍

UDP --- 用户数据报协议, 是一个无连接的简单的面向数据报的传输层协议。 UDP不提供可靠性, 它只是把应用程序传给IP层的数据报发送出去, 但是并不能保证它们能到达目的地。 由于UDP在传输数据报前不用在客户和服务器之间建立一个连接, 且没有超时重发等机制, 故而传输速度很快。
UDP是一种面向无连接的协议, 每个数据报都是一个独立的信息, 包括完整的源地址或目的地址, 它在网络上以任何可能的路径传往目的地, 因此能否到达目的地, 到达目的地的时间以及内容的正确性都是不能被保证的。

【 适用情况】
UDP是面向消息的协议, 通信时不需要建立连接, 数据的传输自然是不可靠的, UDP一般用于多点通信和实时的数据业务, 比如:

  • 语音广播
  • 视频
  • QQ
  • TFTP(简单文件传送)
  • SNMP( 简单网络管理协议)
  • RIP( 路由信息协议, 如报告股票市场, 航空信息)
  • DNS(域名解释)

UDP操作简单, 而且仅需要较少的监护, 因此通常用于局域网高可靠性的分散系统中client/server应用程序。 例如视频会议系统, 并不要求音频视频数据绝对的正确, 只要保证连贯性就可以了, 这种情况下显然使用UDP会更合理一些。

技术分享图片

2、udp网络程序-发送数据

创建一个udp客户端程序的流程是简单, 具体步骤如下:

  1. 创建客户端套接字
  2. 发送/接收数据
  3. 关闭套接字
from socket import *
#1.创建套接字
udpSocket = socket(AF_INET,SOCK_DGRAM)
#2.准备接收方的地址
sendAddr = (‘192.168.1.103‘,7777)
#3.从键盘获取数据
sendData = input(‘请输入要发送的数据:‘)
#4发送数据到指定的电脑上
udpSocket.sendto(sendData.encoding(‘utf-8‘),sendAddr)
#5.关闭套接字
udpSocket.ckose()

3、udp网络程序-接收数据

from socket import *
#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#2. 准备接收方的地址
sendAddr = (‘192.168.1.103‘, 7777)
#3. 从键盘获取数据
sendData = input("请输入要发送的数据:")
#4. 发送数据到指定的电脑上
udpSocket.sendto(sendData.encoding(‘utf-8‘), sendAddr)
#5. 等待接收对方发送的数据
recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数
#6. 显示对方发送的数据
print(recvData)
#7. 关闭套接字
udpSocket.close()

4、udp网络程序-端口问题

重新运行多次脚本端口会发生改变,原因在于, 当重新运行时, 如果没有确定到底用哪个, 系统默认会随机分配

端口唯一标识这个程序,如果其他电脑上的网络程序如果想要向此程序发送数据, 那么就需要向这个端口标识的程序发送即可

5、udp绑定信息

如果需要做成一个服务器端的程序的话,端口号是需要绑定的

from socket import *
#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#2. 绑定本地的相关信息, 如果一个网络程序不绑定, 则系统会随机分配
bindAddr = (‘‘, 7788) # ip地址和端口号, ip一般不用写, 表示本机的任何一个ip
udpSocket.bind(bindAddr)
#3. 等待接收对方发送的数据
# 返回一个元组(数据字节,(发送放的ip,port))
recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最?字节数
#4. 处理数据
msg = recvData[0].decode(‘gbk‘)
ip = recvData[1][0]
port = recvData[1][1]
#5. 显示接收到的数据
myMsg = ‘【Receive from %s : %s】:%s‘%(ip,port,msg)
print(myMsg)
#6. 关闭sockcet
myUDP.close()

总结

一个udp网络程序, 可以不绑定, 此时操作系统会随机进行分配一个端口, 如果重新运行次程序端口可能会发生变化
一个udp网络程序, 也可以绑定信息( ip地址, 端口号) , 如果绑定成功, 那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的

6、udp网络通信过程

技术分享图片

7、udp应用: echo服务器

Echo服务是一种非常有用的用于调试和检测的工具。这个协议的作用也十分简单,接收到什么原封发回就是了。

from socket import *
#1.创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#2.绑定本地的相关信息
bindAddr = (‘‘, 7777) #ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udpSocket.bind(bindAddr)
num = 1
while True:
    #3.等待接收对方发送的数据
    recvData = udpSocket.recvfrom(1024) #1024表示本次接收的最大字节数
    #4.将接收到的数据再发送给对方
    udpSocket.sendto(recvData[0], recvData[1])
    #recvData是一个元组,[0]是元组中的第一个元素,存的是接收到的消息,
    #[1]是第二个元素,消息的来源,即发送方的IP地址和端口号
    
    #5. 统计信息
    print(‘已经将接收到的第%d个数据返回给对方,内容为:%s‘%(num,recvData[0]))
    num+=1

#6. 关闭套接字
udpSocket.close()

8、udp应用: 聊天室

from socket import *
from time import ctime
#1. 创建套接字
udpSocket = socket(AF_INET, SOCK_DGRAM)
#2. 绑定本地的相关信息
bindAddr = (‘‘, 7788) # ip地址和端口号,ip一般不用写,表示本机的任何一个ip
udpSocket.bind(bindAddr)
while True:
    #3. 等待接收对方发送的数据
    recvData = udpSocket.recvfrom(1024) # 1024表示本次接收的最大字节数
    #4. 打印信息
    print(‘【 %s】 %s:%s‘%(ctime(),recvData[1],recvData[0]))

#5. 关闭套接字
udpSocket.close()

==强势插入——基于udp协议多线程接收数据并回复数据==

from socket import socket,AF_INET,SOCK_STREAM,SOCK_DGRAM
from threading import Thread
from time import sleep

class MyThread(Thread):
    def __init__(self,udpSocket,recvData,recvAddress):
        self.recvData = recvData
        self.recvAddress = recvAddress
        self.udpSocket = udpSocket
        Thread.__init__(self)

    def run(self):
        sendData = self.recvData.decode(‘gbk‘) + ‘--收到了
‘
        self.udpSocket.sendto(sendData.encode(‘gbk‘),self.recvAddress)

#1. 创建基于UDP协议的socket对象
myUDP = socket(AF_INET,SOCK_DGRAM)
#2. 监听指定的端口号
myUDP.bind((‘‘,8888))
while True:
    #3. 接收数据,地址
    print(‘等待接收中......‘)
    #myUDP.recvfrom(1024)得到的是一个(数据,(ip,port))
    recvData,recvAddress = myUDP.recvfrom(1024)
    #4. 回复
    MyThread(myUDP,recvData,recvAddress).start()

#5. 关闭sockcet
myUDP.close()

9、udp总结

  1. udp是TCP/IP协议族中的一种协议能够完成不同机器上的程序间的数据通信
  2. udp服务器、 客户端
    udp的服务器和客户端的区分: 往往是通过请求服务 和 提供服务来进行区分
    请求服务的一方称为: 客户端
    提供服务的一方称为: 服务器
  3. udp绑定问题
    一般情况下, 服务器端, 需要绑定端口, 目的是为了让其他的客户端能够正确发送到此进程
    客户端, 一般不需要绑定, 而是让操作系统随机分配, 这样就不会因为需要绑定的端口被占用而导致程序无法运行的情况

10、给飞秋发信息

应用程序可以在通用的tcp/ip协议基础上,加上自己的判断,组成新的应用层协议。

比如飞秋,使用的是udp协议,在此基础上包装成了IPMSG协议。

格式:

  • 版本号:包编号:发送者姓名:发送者机器名:命令字:消息
  • 1:12323434:帅哥一枚:奇酷的电脑:32:大叫好,我是一个名大帅哥
  • 注:现行的IPMSG协议的版本是1
import socket

#创建socket对象
udpSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#目的地
destAdress = (‘192.168.11.74‘,2425)
#消息内容
sendMsg = input(‘>>‘)
#编码
sendMsg = sendMsg.encode(‘gbk‘)
#发送
udpSocket.sendto(sendMsg,destAdress)

#关闭socket对象
udpSocket.close()
print(‘over......‘)

12、udp给飞秋广播发消息(群发)

from socket import *

#创建socket对象
myUDP = socket(AF_INET,SOCK_DGRAM)
#设置可以向广播地址发消息
myUDP.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
#目的地
destAdress = (‘<broadcast>‘,2425)
#消息内容
sendMsg = input(‘>>‘)
#编码
sendMsg = sendMsg.encode(‘gbk‘)
#发送
myUDP.sendto(sendMsg,destAdress)

#关闭socket对象
myUDP.close()
print(‘over......‘)

13、模拟QQ

from threading import Thread
from socket import *


# 1. 收数据,然后打印
def recvData():
    while True:
        recvInfo = udpSocket.recvfrom(1024)
        print(">>%s:%s" % (str(recvInfo[1]), recvInfo[0]))


# 2. 检测键盘,发数据
def sendData():
    while True:
        sendInfo = input("<<")
        udpSocket.sendto(sendInfo.encode("gb2312"), (destIp, destPort))


udpSocket = None
destIp = ""
destPort = 0


def main():
    global udpSocket
    global destIp
    global destPort

    destIp = input("对方的ip:")
    destPort = int(input("对方的port:"))

    udpSocket = socket(AF_INET, SOCK_DGRAM)
    udpSocket.bind(("", 4567))

    tr = Thread(target=recvData)
    ts = Thread(target=sendData)

    tr.start()
    ts.start()

    # tr.join()
    # ts.join()


if __name__ == "__main__":
    main()








以上是关于07.网络编程-2.UDP的主要内容,如果未能解决你的问题,请参考以下文章

Linux:UDP Socket编程(代码实战)

JAVA网络编程知识学习

❤️怒肝三万字,史诗的保姆网络编程教学❤️

使用实体框架迁移时 SQL Server 连接抛出异常 - 添加代码片段

ViewPager2:以编程方式选择特定片段

VSCode自定义代码片段——JS中的面向对象编程