如何确保客户端在 Python 中使用 UDP 套接字收到我的消息?
How can I ensure that a client received my message using UDP sockets in Python?
我正在 python 中使用 UDP 套接字编写学校练习,我需要在服务器和客户端之间交换一些信息(例如,整数、字符串等)。
我写了这个函数来确保客户端收到从服务器发送的消息,反之亦然:
import socket
BUFFER_SIZE = 1024
def send_udp_mgs(origin, destination, msg):
msg = str(msg).encode('utf8')
origin.sendto(msg, destination) # sending message
# I never receive confirmation
opt, _ = origin.recvfrom(BUFFER_SIZE) # Code stucks here
opt = opt.decode('utf8')
print(opt)
def receive_udp_msg(destination):
msg, origin = destination.recvfrom(BUFFER_SIZE) # receiving message OK
# This is the message sent as confirmation but is never received
destination.sendto("CHECK".encode('utf8'), origin) # sent but not received
msg = msg.decode()
return msg
我希望代码能够在发送消息后与接收确认的函数一起正常工作,但它在等待确认时卡住了。客户端发送确认,但服务器从未收到它。除此之外,客户端接收消息很好,只是向服务器的确认返回失败。
这是服务器代码:
def client_thread (s, c):
print("Connection petition from", c)
global n_cons
cport = PORT + n_cons
send_udp_mgs(s, c, cport)
return
# UDP socket acting as server
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((IP, PORT))
while True:
data, addr = s.recvfrom(BUFFER_SIZE)
if data.decode() == CONNECT:
n_cons += 1
try:
Thread(target=client_thread, args=(s,), kwargs={'c':addr}).start()
except:
print("Error creating thread")
break
客户代码
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s = (IP, PORT)
# Connecting to the server
c.sendto(CONNECT.encode('utf8'), s)
cport = receive_udp_msg(c)
我无法让你的程序在你说的确切停止点停止,但我找到了一个我怀疑有类似原因的问题:
如果有多个客户端,等待一个客户端确认的线程可以收到下一个客户端的CONNECT
消息,服务器的"main loop"可以收到确认消息。
您无法避免这个问题:除非您可以控制所有客户端发送数据的时间,否则您无法在使用 UDP 时为不同的客户端分离线程。我建议使用 select
, selectors
, or asyncio
, or just asyncio
's socket functions 在您的套接字上执行操作。
但还有其他问题需要考虑:您为什么要尝试确认 UDP 消息?如果您需要确保连接的另一端收到您发送的内容,为什么不使用 TCP 或其他具有确保内置传送机制的协议?
如果你真的需要使用UDP,你需要至少制作一个数据结构来跟踪试图"connect,"和关于它们的其他信息 "connections." 但是 UDP 是明确无连接的。
作为不相关的评论,client_thread
中的 cport
是否暗示您计划为每个客户端按顺序 创建一个新端口?如果是这样,请考虑 (a) 您只能打开这么多端口,(b) 许多其他进程正在使用其中一个端口,(c) 除非 n_cons
永远不会关闭,否则此进程 会使用这些端口吗,以及 (d) 你需要那么多端口做什么? (另见 this answer。)
我正在 python 中使用 UDP 套接字编写学校练习,我需要在服务器和客户端之间交换一些信息(例如,整数、字符串等)。
我写了这个函数来确保客户端收到从服务器发送的消息,反之亦然:
import socket
BUFFER_SIZE = 1024
def send_udp_mgs(origin, destination, msg):
msg = str(msg).encode('utf8')
origin.sendto(msg, destination) # sending message
# I never receive confirmation
opt, _ = origin.recvfrom(BUFFER_SIZE) # Code stucks here
opt = opt.decode('utf8')
print(opt)
def receive_udp_msg(destination):
msg, origin = destination.recvfrom(BUFFER_SIZE) # receiving message OK
# This is the message sent as confirmation but is never received
destination.sendto("CHECK".encode('utf8'), origin) # sent but not received
msg = msg.decode()
return msg
我希望代码能够在发送消息后与接收确认的函数一起正常工作,但它在等待确认时卡住了。客户端发送确认,但服务器从未收到它。除此之外,客户端接收消息很好,只是向服务器的确认返回失败。
这是服务器代码:
def client_thread (s, c):
print("Connection petition from", c)
global n_cons
cport = PORT + n_cons
send_udp_mgs(s, c, cport)
return
# UDP socket acting as server
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((IP, PORT))
while True:
data, addr = s.recvfrom(BUFFER_SIZE)
if data.decode() == CONNECT:
n_cons += 1
try:
Thread(target=client_thread, args=(s,), kwargs={'c':addr}).start()
except:
print("Error creating thread")
break
客户代码
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s = (IP, PORT)
# Connecting to the server
c.sendto(CONNECT.encode('utf8'), s)
cport = receive_udp_msg(c)
我无法让你的程序在你说的确切停止点停止,但我找到了一个我怀疑有类似原因的问题:
如果有多个客户端,等待一个客户端确认的线程可以收到下一个客户端的CONNECT
消息,服务器的"main loop"可以收到确认消息。
您无法避免这个问题:除非您可以控制所有客户端发送数据的时间,否则您无法在使用 UDP 时为不同的客户端分离线程。我建议使用 select
, selectors
, or asyncio
, or just asyncio
's socket functions 在您的套接字上执行操作。
但还有其他问题需要考虑:您为什么要尝试确认 UDP 消息?如果您需要确保连接的另一端收到您发送的内容,为什么不使用 TCP 或其他具有确保内置传送机制的协议?
如果你真的需要使用UDP,你需要至少制作一个数据结构来跟踪试图"connect,"和关于它们的其他信息 "connections." 但是 UDP 是明确无连接的。
作为不相关的评论,client_thread
中的 cport
是否暗示您计划为每个客户端按顺序 创建一个新端口?如果是这样,请考虑 (a) 您只能打开这么多端口,(b) 许多其他进程正在使用其中一个端口,(c) 除非 n_cons
永远不会关闭,否则此进程 会使用这些端口吗,以及 (d) 你需要那么多端口做什么? (另见 this answer。)