【问题标题】:Python UDP socketserver returning empty messagePython UDP 套接字服务器返回空消息
【发布时间】:2023-02-10 06:56:46
【问题描述】:

我有一个 UDP 套接字服务器程序,用于演示 UDP 的工作原理(服务器和客户端的代码如下)。我在服务器上运行它,然后让 client.py 程序发送消息并接收回复。不幸的是,我遇到了一个似乎只发生在校园 Wifi 上的问题。在校园wifi上,客户端收不到响应。

使用 Wireshark 进行故障排除显示了问题。由于某种原因,UDP 服务器正在响应两条 UDP 消息 - 一条为空,一条包含响应消息。这些消息在 Wireshark 中记录为大约间隔 0.000002 秒。在有线网络上,有响应的始终排在第一位,而在 Wifi 上,空消息始终排在第一位。由于客户端正在等待单个消息响应,因此当空消息返回时,客户端打印并退出,并且永远不会看到实际的响应。

我知道我可以编写客户端来监听这两条消息并打印出有数据的消息,但我宁愿尝试弄清楚发生了什么。为什么 socketserver 首先响应两条消息,我怎样才能让它只发送一条消息?或者至少先发送数据。

server.py:

import socketserver


class MyUDPRequestHandler(socketserver.DatagramRequestHandler):
    def handle(self):

        data = self.request[0].strip()
        socket = self.request[1]
        # just send back the same data, but lower-cased
        socket.sendto(data.lower(), self.client_address)


if __name__ == "__main__":
    with socketserver.UDPServer(("0.0.0.0", 9091), MyUDPRequestHandler) as server:
        server.serve_forever()

client.py:

import socket

HOST, PORT = "localhost", 9091
message = "NOW I AM SHOUTING"  # The UDP server will lowercase the message

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.sendto(bytes(message + "\n", "utf-8"), (HOST, PORT))
received = str(sock.recv(1024), "utf-8")

print("Sent:     {}".format(message))
print("Received: {}".format(received))

【问题讨论】:

  • 如果您暂时从 handle(self) 方法中删除 .strip().lower() 调用,神秘行为是否会继续发生?
  • 因此,无论哪种方式,您都会收到两个,但顺序有时会在无线上发生变化?
  • 顺序似乎每次都在无线上改变,是的,无论哪种方式,我都会收到两条响应消息。
  • @JeremyFriesner 条带是必需的,删除 lower() 不会改变任何东西。
  • @Ryan 调试所需的条带如何?

标签: python sockets udp socketserver


【解决方案1】:

我重复了这个问题,它是socketserver。请注意下面DatagramRequestHandler 的定义:

class DatagramRequestHandler(BaseRequestHandler):

    """Define self.rfile and self.wfile for datagram sockets."""

    def setup(self):
        from io import BytesIO
        self.packet, self.socket = self.request
        self.rfile = BytesIO(self.packet)
        self.wfile = BytesIO()

    def finish(self):
        self.socket.sendto(self.wfile.getvalue(), self.client_address)

数据包作为rfile 放入缓冲区,应从那里读取,然后写回wfile 缓冲区。 finish 发送数据包。处理程序不应调用 sendto 本身:

import socketserver

class MyUDPRequestHandler(socketserver.DatagramRequestHandler):
    def handle(self):
        data = self.rfile.read()
        self.wfile.write(data.strip().lower())

if __name__ == "__main__":
    with socketserver.UDPServer(("0.0.0.0", 9091), MyUDPRequestHandler) as server:
        server.serve_forever()

但是只使用一个简单的套接字作为服务器也可以正常工作:

import socket

s = socket.socket(type=socket.SOCK_DGRAM)
s.bind(('', 9091))
while True:
    data, client = s.recvfrom(2048)
    s.sendto(data.strip().lower(), client)

请注意,UDP 数据包不能保证以相同的顺序传送或传送,因此原始代码中两个数据包更改顺序的问题并不奇怪。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    • 2021-03-21
    • 2012-07-22
    • 1970-01-01
    • 2016-11-06
    • 2015-03-09
    • 2020-06-23
    相关资源
    最近更新 更多