分类
技术

在Socket通信中,UDP协议下使用recvfrom获取的端口号与sendto发送的端口不一致原因分析

最近在尝试Socket通信时,发现在UDP协议下,Sever端使用recvfrom方法获取发送端的ip地址和端口号时,IP地址正确,但是端口号总是与Client端sendto方法指定的端口号不一致,代码与结果如下

Sever端:

import socket
# 持续通信
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 创建UDP类型的套接字
s.bind(("127.0.0.1", 46551))  # 绑定端口,ip可以不写
print("等待接收数据!")
while True:
    recv_data, recv_addr = s.recvfrom(1024)  # 1024表示本次接收的最大字节数,recvfrom一直监听知道由数据被接受
    data = recv_data.decode('gbk')
    print(f"收到远程信息:{data},from {recv_addr}")
    if data == "exit":
        print("结束聊天!")
        break
s.close()

Client端:

import socket
# UDP客户端持续发送消息代码
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 创建UDP类型的套接字
#s.bind(("127.0.0.1", 46552)) #UDPclient端可以不绑定端口,client端不绑定时是随机端口发送的
addr = ("127.0.0.1", 46551)
while True:
    data = input("请输入:")
    s.sendto(data.encode("gbk"), addr)
    if data == "exit":
        print("结束聊天!")
        break
s.close()

结果:

可以看到终端中输出的信息,Sever端recvfrom方法接收到的端口号不是sendto指定的46551端口,而且每次启动后Sever端接收到的端口都不一样,这里其实是因为在UDP协议下,Client端并没有绑定端口号,所以是由系统随机指定空闲端口发送的,如果在Client端绑定指定的端口 s.bind(("127.0.0.1", 46552)) 便可用自己指定的端口 46552 来发送信息。

因为UDP是无连接协议,通信的两端(即发送方和接收方)可以任意选择任何空闲的端口来进行通信,对于接收方来说,获取到的端口号并不一定与发送方所用的端口号相同,而是与发送方所在主机的端口号相同。换句话说,发送方和接收方使用的是各自的端口号来进行通信,而不是共享一个端口号。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

在此处输入验证码 : *

Reload Image