UDP

发布时间 2023-08-12 22:34:06作者: Allen_Hao

UDP不像TCP创建连接时有3次握手,而是直接发送数据,不管对方是否接收到。

UDP网络通信不区分客户端和服务端。

 

UDP收发数据的步骤

  1.创建UDP套接字对象
  2.直接发送数据
  3.读取数据
  4.关闭套接字

 

示例

服务端

 1 '''
 2 UDP应该说没有服务端和客户端,只是习惯称发请求的为客户端端,对方为服务端
 3 
 4 最佳实践:
 5     1. 创建UDP套接字:使用socket.socket()函数创建一个UDP套接字对象。
 6         import socket
 7         # 创建UDP套接字
 8         udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 9     2. 绑定地址和端口:使用bind()方法将套接字绑定到指定的IP地址和端口。
10         # 绑定地址和端口
11         udp_socket.bind(('127.0.0.1', 8000))
12     3. 发送数据:使用sendto()方法发送数据给指定的目标地址和端口。
13         # 发送数据
14         data = b"Hello, UDP server!"
15         udp_socket.sendto(data, ('127.0.0.1', 9000))
16     4. 接收数据:使用recvfrom()方法接收来自其他主机的数据,并返回接收到的数据和发送方的地址信息。
17         # 接收数据
18         data, addr = udp_socket.recvfrom(1024)
19         print("Received data:", data.decode())
20         print("From address:", addr)
21     5. 关闭套接字:使用close()方法关闭套接字。
22         # 关闭套接字
23         udp_socket.close()
24 '''
25 import socket
26 
27 # 创建UDP套接字
28 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
29 udp_socket.bind(('127.0.0.1', 8000))
30 
31 while True:
32     # 接收数据
33     data, addr = udp_socket.recvfrom(1024)
34     print("Received data:", data.decode())
35 
36     # 发送数据
37     message = input("Enter message to send: ")
38     udp_socket.sendto(message.encode(), addr)

客户端

import socket

# 创建UDP套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while True:
    # 发送数据
    message = input("Enter message to send: ")
    udp_socket.sendto(message.encode(), ('127.0.0.1', 8000))

    # 接收数据
    data, addr = udp_socket.recvfrom(1024)
    print("Received data:", data.decode())

这个案例展示了一个简单的UDP聊天应用程序,服务器和客户端可以互相发送消息。服务器接收到客户端发送的消息后,将其显示在控制台,并向客户端回复一个消息。

 广播

 1 import socket
 2 
 3 # 创建UDP套接字
 4 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 5 udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
 6 
 7 # 广播地址和端口号
 8 broadcast_address = '<broadcast>'
 9 port = 8000
10 
11 # 发送消息到广播地址
12 message = "Hello, broadcast!"
13 udp_socket.sendto(message.encode(), (broadcast_address, port))  # 
14 
15 # 接收来自服务器的响应
16 response, address = udp_socket.recvfrom(1024)
17 print("Received response from server:", response.decode())
18 print("Server address:", address)
19 
20 # 关闭套接字
21 udp_socket.close()
# 服务端代码,用于处理广播消息
import socket

# 创建UDP套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# 绑定到特定的IP地址和端口号
server_address = ('', 8000)
udp_socket.bind(server_address)

while True:
    # 接收来自客户端的请求
    data, address = udp_socket.recvfrom(1024)
    print("Received request from client:", data.decode())
    print("Client address:", address)

    # 发送回复消息
    response = "Hello, client!"
    udp_socket.sendto(response.encode(), address)


# 客户端代码,用于发送广播消息
import socket

# 创建UDP套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

# 广播地址(是广播地址的,也可以这样写)和端口号(端口号是服务端的端口)
broadcast_address = '<broadcast>'
port = 8000

# 发送广播消息
message = "Service discovery request"
udp_socket.sendto(message.encode(), (broadcast_address, port))

# 接收来自服务端的回复消息
response, address = udp_socket.recvfrom(1024)
print("Received response from server:", response.decode())
print("Server address:", address)

# 关闭套接字
udp_socket.close()

获取广播地址的代码:

import socket
import struct


def calculate_broadcast_address(ip_address, subnet_mask):
    ip_bytes = socket.inet_aton(ip_address)
    mask_bytes = socket.inet_aton(subnet_mask)

    # 将IP地址和子网掩码转换为32位整数
    ip_int = struct.unpack('!I', ip_bytes)[0]
    mask_int = struct.unpack('!I', mask_bytes)[0]

    # 计算广播地址
    broadcast_int = ip_int | (~mask_int & 0xFFFFFFFF)

    # 将广播地址转换为字符串形式
    broadcast_address = socket.inet_ntoa(struct.pack('!I', broadcast_int))

    return broadcast_address


ip_address = '192.168.68.1'  # 自己电脑的ip
subnet_mask = '255.255.255.0'  # ip对于的子网掩码
broadcast_address = calculate_broadcast_address(ip_address, subnet_mask)
print("Broadcast Address:", broadcast_address)

客户端:

 服务端:

 参考:https://www.bilibili.com/video/BV1dZ4y1o7Az/?spm_id_from=333.337.search-card.all.click&vd_source=551c4b0e8145ff81bc32a29ff09a3238