36. UDP网络编程

news/2025/2/26 1:33:22/文章来源:https://www.cnblogs.com/FlurryHeart/p/18565136

一、什么是UDP协议

  相对于 TCP 协议,UDP 协议则是面向无连接的协议。使用 UDP 协议时,不需要建立连接,只需要知道对象的 IP 地址和端口号,就可以直接发数据包。但是,数据无法保证一定到达。虽然用 UDP 传输数据不可靠,但它的优点是比 TCP 协议的速度快。对于不要求可靠到达的数据而言,就可以使用 UDP 协议。

UDP通信

UDP 每次发送数据的时候,都需要写上接收方的 IP 和 PORT;

二、UDP网络编程

2.1、创建UDP服务器

  创建 UDP 服务器的伪代码如下:

import socket                       # 导入socket模块ss =  socket.socket()               # 创建服务器套接字
ss.bind()                           # 套接字与地址绑定while True:                         # 监听连接cs = ss.recvfrom()/ss.sendto()   # 对话(接收/发送)ss.close()                          # 关闭服务器套接字

  UDP 和 TCP 服务器之间的一个显著差异是,因为数据报套接字是无连接的,所以就没有为了通信成功而使一个客户端连接到一个独立的套接字 “转换” 的操作。这些服务器仅仅接收消息,并有可能回复数据。

from socket import socket
from socket import AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_REUSEADDR
from time import ctimeHOST = "127.0.0.1"
PORT = 8080
ADDRESS = (HOST, PORT)udp_server = socket(AF_INET, SOCK_DGRAM)                        # 创建服务器套接字
udp_server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)              # 解决端口占用问题
udp_server.bind(ADDRESS)                                        # 套接字与地址绑定while True:                                                     # 通信循环recv_data, client_addr = udp_server.recvfrom(1024)          # 服务端接收消息,单次最大接收为1024个字节print(f"收到客户端【{client_addr}】数据:{recv_data.decode('utf-8')}")udp_server.sendto(f"【{ctime()}】 {recv_data.decode('utf-8')}".encode("utf-8"), client_addr)     # 服务端发送消息udp_server.close()                                              # 关闭服务器套接字

  对 socket() 的调用的不同之处仅仅在于,我们现在需要一个 数据报/UDP 套接字类型,但是 bind() 的调用方式与 TCP 服务器版本的相同。因为 UDP 是无连接的,所以这里没有调用 “监听传入的连接”。

2.2、创建UDP客户端

  创建 UDP 服务器的伪代码如下:

import socket                       # 导入socket模块cs =  socket.socket()               # 创建客户端套接字while True:                         # 通信循环cs.sendto()/cs.recvfrom()       # 对话(发送/接收)cs.close()                          # 关闭客户端套接字

  UDP 客户端循环工作方式几乎和 TCP 客户端一样。唯一的区别是,事先不需要建立与 UDP 服务器的连接,只是简单的发送一条消息并等待服务器的回复。

from socket import socket
from socket import AF_INET, SOCK_DGRAMHOST = "127.0.0.1"
PORT = 8080
ADDRESS = (HOST, PORT)udp_client = socket(AF_INET, SOCK_DGRAM)                            # 创建客户器套接字while True:                                                         # 通信循环send_data = input("请输入要发送的数据: ").strip()udp_client.sendto(send_data.encode("utf-8"), ADDRESS)           # 客户端发送数据recv_data, server_addr = udp_client.recvfrom(1024)              # 客户端接收数据,单次最大接收为1024个字节print(f"收到服务端【{server_addr}】返回的数据:{recv_data.decode('utf-8')}")udp_client.close()                                                  # 关闭客户端套接字

2.3、执行UDP服务器和客户端

  如果先运行客户端,那么将无法进行任何连接,因为没有服务器等待接受请求。服务器可以视为一个被动伙伴,因为必须首先建立自己,然后被动的等待连接。另一方面,客户端是一个主动的合作伙伴,因为它主动发起一个连接。换句话说,首先启动服务器(在任何客户端试图连接之前)。

  在开发中,创建这种 “友好的” 退出方式的一种方法就是,将服务器的 while 循环放在一个 try-except 语句中的 except 子句中,并监控 EOFError 或 KeyboardInterrupt 异常,这样你就可以在 except 或 finally 子句中关闭服务器的套接字。

三、UDP广播

  UDP 广播是一种网络通信的方式,在广域网或局域网中,UDP 广播可以向多个目标主机发送数据包,使得网络中的所有设备都能接收到广播消息。使用广播之后,socket 只需要发送一次 UDP 数据,就可以发送给本局域网中的任何一台电脑相同的数据。

import socket                       # 导入socket模块ss =  socket.socket()               # 创建服务器套接字
ss.setsockopt()                     # 设置UDP套接字允许广播
ss.bind()                           # 套接字与地址绑定while True:                         # 监听连接cs = ss.recvfrom()/ss.sendto()   # 对话(接收/发送)ss.close()                          # 关闭服务器套接字
from socket import socket
from socket import AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_BROADCAST
from time import ctimeHOST = "127.0.0.1"
PORT = 8080
ADDRESS = (HOST, PORT)BROADCAST_HOST = "<broadcast>"                                              # <broadcast>会自动改为本局域网的广播ip
BROADCAST_PORT = 8086
BROADCAST_ADDRESS = (BROADCAST_HOST, BROADCAST_PORT)udp_server = socket(AF_INET, SOCK_DGRAM)                                    # 创建服务器套接字
udp_server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)                          # 设置UDP允许广播
udp_server.bind(ADDRESS)                                                    # 套接字与地址绑定while True:                                                                 # 通信循环content = input("请输入你要广播的内容:")udp_server.sendto(f"【{ctime()}】{content}".encode("utf-8"), BROADCAST_ADDRESS)  # 服务端发送广播内容data, client_addr = udp_server.recvfrom(1024)                           # 服务端接收消息,单次最大接收为1024个字节print(f"收到客户端【{client_addr}】返回的数据:{data.decode('utf-8')}")udp_server.close()                                                          # 关闭服务器套接字

四、UDP聊天室

from socket import socket
from socket import AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_REUSEADDR
from time import ctime
from threading import Thread
from queue import QueueHOST = "127.0.0.1"
PORT = 8080
ADDRESS = (HOST, PORT)udp_socket = socket(AF_INET, SOCK_DGRAM)                            # 创建服务器套接字
udp_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)                  # 解决端口占用问题
udp_socket.bind(ADDRESS)                                            # 套接字与地址绑定def send_msg(q):while True:dest_ip = input("请输入对方的IP地址:").strip()dest_port = int(input("请输入对方的PORT:").strip())while True:msg = input("请输入要发送的数据:").strip()if not msg:breakudp_socket.sendto(f"{msg}".encode("utf-8"), (dest_ip, dest_port))info = f"【{ctime()}】向【{(dest_ip, dest_port)}】发送数据:{msg}"q.put(info)def recv_msg(q):while True:try:msg, dest_address = udp_socket.recvfrom(1024)           # 服务端接收消息,单次最大接收为1024个字节info = f"【{ctime()}】收到【{dest_address}】发送的数据:{msg.decode('utf-8')}"q.put(info)print(info)except:passdef chat_history(q):while True:content = q.get()                                           # 从Queue中读取数据# 将数据写入到文件中with open("./chat.txt", "a", encoding="utf-8") as f:f.write(content)f.write("\n")if __name__ == "__main__":q = Queue()                                                     # 创建一个队列send_msg_thread = Thread(target=send_msg, args=(q,))            # 创建一个新的线程对象,用来发送数据recv_msg_thread = Thread(target=recv_msg, args=(q,))            # 创建一个新的线程对象,用来接受数据chat_history_thread = Thread(target=chat_history, args=(q,))    # 创建一个新的线程对象,用来保存聊天记录send_msg_thread.start()recv_msg_thread.start()chat_history_thread.start()send_msg_thread.join()recv_msg_thread.join()chat_history_thread.join()udp_socket.close()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/840046.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

社区发布非官方龙架构 .NET 9 SDK 发行版

随着.NET 9的发布,龙芯的Loongarch 架构的.NET 9 SDK的发布也提上了日程,在龙芯.NET 的官方支持之外,今年在社区有一个非官方龙架构 .NET SDK 发行版(https://github.com/loongson-community/dotnet-unofficial-build)在2024.11.22 正式发布了.NET 9 SDK, 发布的包放在了…

jQuery带炫酷轮播图效果的Lightbox弹出层插件

在线预览 下载这是一款jQuery带炫酷轮播图效果的Lightbox弹出层插件。该lightbox插件在弹出层中,可以对所有图片进行轮播。它的特点还有:简单、速度快。 响应式设计。 可以显示每张图片的状态。 在弹出层中可以设置图片的标题和文字。 支持CSS3动画。 使用方法 在页面中引入…

jQuery添加到购物车动画特效插件

在线预览 下载这是一款jQuery添加到购物车动画特效插件。该插件可以非常方便的制作出点击商品购买按钮,商品飞入购物车的动画特效。使用方法 在页面中引入jquery和jquery.animate_from_to-1.0.js文件。<script src="js/jquery.min.js" type="text/javascri…

实验四 类的组合,继承,模板类,标准库

一、实验目的知道什么是类模板,会正确定义和使用简单的类模板 会使用C++正确定义,使用派生类 加深对类的组合机制(has-a),类的继承机制(is-a)的领悟和理解 练习标准库string,vector的用法,能基于问题场景灵活使用 针对具体场景,练习运用面向对象思维进行设计,组合使用标…

IDEA中如何查看jar包反编译源代码

前言 大家好,我是小徐啊。IDEA是我们常用的Java开发工具,非常好用,功能也非常强大。而Java的开发,又涉及到类的编译,比如java文件编译成class文件,打jar包其实也是如此。 不过有时候,我们可能需要排查下jar包里面的逻辑,但这时候用压缩工具,比如7-zip等解压出来,发现…

4~6次作业总结

一、前言答题判题程序-4知识点:主要采用类的封装,将对象的属性和方法结合在一起,仅通过公共接口与外部进行交互,满足程序要求;通过try-catch语句来实现异常处理,当程序执行过程中遇到异常情况时,抛出一个异常对象,并由相应的catch块捕获并处理。 题量分析:涉及到一个相…

python中调用 .net 的 dll 时,报错:Exception has occurred: TypeLoadException

1、问题在 python3 中想调用 .net8 的 dll 。在运行时报错:Exception has occurred: TypeLoadException 未能从程序集“System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”中加载类型“System.Runtime.CompilerServices.NullableContextAt…

2025--炼石计划-- 11 月 23 日 --NOIP 模拟赛 #23

2025--炼石计划-- 11 月 23 日 --NOIP 模拟赛 #23\(T1\) A. 排序 \(100pts\)仅考虑临项比较时必要的一位的选择即可。点击查看代码 ll a[1000010],ans[35][2]; ll ask() {ll x=0;for(ll i=31;i>=0;i--){if(ans[i][0]!=0&&ans[i][1]!=0){return -1;}if(ans[i][1]!=…

《计算机基础与程序设计》第九周学习总结

学期(2024-2025-1) 学号(20241412) 《计算机基础与程序设计》第九周学习总结 作业信息这个作业属于哪个课程 <班级的链接> 2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接> 2024-2025-1计算机基础与程序设计第一周作业)这个作业的目标…

团队作业5

团队作业5信息项 内容课程名称 广工计院计科34班软工作业要求位置 https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13235作业目标 测试与发布(Alpha版本)GitHub链接 https://github.com/axunlu/gdut-shop团队简介队名:小飞棍队 团队成员:姓名 学号罗振烘(组长…

关于sqlmap中--os-shell如何getshell的源码学习

在这里记录一下我较感兴趣的sqlmap中getshell相关部分的分析,简单从源码的角度看看sqlmap是如何通过--os-shell拿服务器shell的。目录前言数据库注入getshell源码分析 前言 最近详细看了@v1ll4n大佬写的几篇关于sqlmap源码分析的文章(sqlmap 内核分析)收获很多。借此机会在这…

2024-11-16

在这里记录一下我较感兴趣的sqlmap中getshell相关部分的分析,简单从源码的角度看看sqlmap是如何通过--os-shell拿服务器shell的。目录前言数据库注入getshell源码分析 前言 最近详细看了@v1ll4n大佬写的几篇关于sqlmap源码分析的文章(sqlmap 内核分析)收获很多。借此机会在这…