首页 > 编程语言 >36. UDP网络编程

36. UDP网络编程

时间:2024-11-23 21:55:22浏览次数:7  
标签:UDP socket 编程 udp 36 import 服务器 接字

一、什么是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 ctime

HOST = "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_DGRAM

HOST = "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 ctime

HOST = "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 Queue

HOST = "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:
                break
            udp_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:
            pass

def 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()

标签:UDP,socket,编程,udp,36,import,服务器,接字
From: https://www.cnblogs.com/FlurryHeart/p/18565136

相关文章

  • 【前端知识】JS实现异步编程
    JS异步编程一、JS异步编程的背景和重要性二、JS异步编程的实现方式三、JS异步编程的示例四、JS异步编程中的错误处理五、JS异步编程的优势JS异步编程是一种编程范式,它允许程序在等待某些操作完成(如I/O操作、网络请求等)时,不必阻塞当前执行线程,而是可以继续执行其他任......
  • shell编程(2)(3)
    目录一、永久环境变量按用户设置永久环境变量文件路径:示例步骤:删除永久环境变量二、脚本程序传递参数怎么实现三、用编程进行数学运算shell中利用expr进行运算运算与变量结合1.变量赋值和基本运算2.使用expr进行运算3.变量拼接4.条件判断结合变量声明:学习......
  • Linux 网络编程之UDP套接字
    前言前面我们对网络的发展,网络的协议、网路传输的流程做了介绍,最后,我们还介绍了IP和端口号,ip +port叫做 套接字socket,本期我们就来介绍UDP套接字编程!目录1、预备知识1.1传输层协议:TCP/UDP1.2网络字节序1.3socket接口1.4sockaddr2、echo_server2.1核......
  • 代码的未来:AI编程工具是否正在重塑技术叙事?
    近年来,AI编程工具的快速发展正逐渐改变编程的方式、技术的普及以及开发者与代码的关系。这不仅是一场技术革命,更是一场叙事重构。曾经,编程被视为一种掌控技术的核心能力,而今天的AI工具让这种掌控变得更加普及,甚至可能将部分人类开发者“边缘化”。在这一背景下,本文结合AI编程工......
  • 并发编程(13)——无锁环形并发队列
    文章目录十三、day131.什么是无锁数据结构?2.环形队列3.实现线程安全的环形队列3.1实现有锁环形队列3.2实现无锁环形队列(有缺陷)3.3实现无锁环形队列(无缺陷)3.3.1pop函数3.3.2push函数3.3.3优化后的pop和push函数3.3.4完整代码4.无锁环形并发队列的优缺点十......
  • C++编程&玩转物联网:用树莓派Pico点亮RGB彩灯世界
    RGBLED彩灯是嵌入式开发中一个简单却充满乐趣的项目元件。通过它,开发者不仅可以学习控制硬件的基础知识,还能探索颜色混合与PWM(脉宽调制)技术的实际应用。本文将以树莓派Pico为核心,带您实现控制RGBLED显示随机颜色的项目。项目简介RGBLED彩灯由红(Red)、绿(Green)、蓝(Blue)三种......
  • java编程开发基础,正则表达式的使用案例Demo
    java编程开发基础,正则表达式的使用案例Demo!实际开发中,经常遇到一些字符串,信息的裁剪和提取操作,正则表达式是经常使用的,下面的案例,可以帮助大家快速的了解和熟悉,正则表达式的使用技巧。packagecom.example.yrlai.util;/***正则表达式的基础练习*/publicclassRege......
  • 计算机网络socket编程(5)_TCP网络编程实现echo_server
    个人主页:C++忠实粉丝欢迎点赞......
  • Python网络编程实战案例
    在当今信息技术高速发展的时代,网络编程成为了软件开发中不可或缺的一部分。Python,以其简洁的语法和强大的功能,成为了网络编程的热门选择。本文将通过几个实战案例,展示Python在网络编程中的应用,包括TCP服务器和客户端的创建、UDP通信、HTTP请求以及多线程服务器的实现。1.TCP......
  • 如何在360评估中控制得分分布?
    得分分布控制作用于评估打分时,评价人对一组被评价人的打分高低进行限制,避免老好人都打高分或恶意都给打低分的情况。得分分布控制包括总分分布控制和各个指标的得分分布控制。注意得分分布控制仅针对一个评价人同时评价多个被评价人时才会产生效果。设置了得分分布控制时,评价......