当前位置:  开发笔记 > 编程语言 > 正文

UDP数据接收上的Python套接字错误.(10054)

如何解决《UDP数据接收上的Python套接字错误.(10054)》经验,为你挑选了1个好方法。

我目前在使用UDP和Python套接字模块时遇到问题.我们有服务器和客户端.当我们向用户发送数据时会出现问题.用户可能通过客户端崩溃,ISP断开连接或其他一些不正确的方法关闭了与服务器的连接.因此,可以将数据发送到封闭的套接字.

当然,使用UDP,您无法判断数据是否真正到达或是否已关闭,因为它不关心(至少,它不会引发异常).但是,如果您发送数据并且它已关闭,则会以某种方式返回数据(???),最终会在sock.recvfrom上出现套接字错误.[Errno 10054]远程主机强行关闭现有连接.几乎看起来像连接的自动响应.

虽然这很好,但可以通过try:except:block来处理(即使它会降低服务器的性能).问题是,我不知道这是来自谁或什么套接字关闭.有没有找到'谁'(ip,socket#)发送这个?它会很棒,因为我可以立即断开它们并将它们从数据中删除.有什么建议?谢谢.

服务器:

import socket

class Server(object):
    def __init__(self):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.connected = {}

    def connect(self):
        self.socket.bind(('127.0.0.1', 5579))

    def find_data(self):
        while 1:
            data, address = self.socket.recvfrom(1024)
            self.got_data(data,address)
            if self.connected.has_key(address):
                pass
            else:
                self.connected[address] = None

    def got_data(self, data, address):
        print "GOT",data,"FROM",address
        for people in self.connected:
            print people
            self.send_data('hi', people)

    def send_data(self, data, address):
        self.socket.sendto(data,address)


if __name__ == '__main__':
    server = Server()
    server.connect()
    print "NOW SEARCHING FOR DATA"
    server.find_data()

客户:

import socket, time

class Client(object):
    def __init__(self):
        self.socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

    def connect(self):
        self.socket.connect(('127.0.0.1', 5579))

    def send_data(self):
        self.socket.sendto('hi',('127.0.0.1', 5579))

    def got_data(self, data, address):
        print "GOT",data,"FROM",address


if __name__ == '__main__':
    client = Client()
    client.connect()
    while 1:
        client.send_data()
        time.sleep(5)

Len Holgate.. 8

首先,这可能是特定于平台的,您没有提到您正在运行的平台; 但是,10054是WSAECONNRESET如此我猜测某种Windows平台.

其次如前所述,与UDP无关.您Connect()在客户端中的呼叫只会导致客户端计算机上的网络代码允许您启动Send()呼叫而不是SendTo()呼叫,并且当您向Send()呼叫提供的地址发出呼叫时,只需将您发送数据的地址默认为Connect().

第三,我很惊讶你得到了WSAECONNRESET而不是ERROR_PORT_UNREACHABLE; 然而,潜在的原因可能是相同的.如果您要发送到的端口上没有打开套接字,则远程计算机上的UDP堆栈可能会发送ICMP端口无法访问错误.因此,如果您的客户端发送数据然后关闭套接字,然后您的服务器将数据发送回客户端地址,您将获得端口无法访问,并且某些版本的Windows可能会将其转换为连接重置错误...

这些ICMP端口无法访问错误的问题在于,它们是通过未通过UDP Recv/RecvFrom调用失败而通过Winsock代码报告的.正如我在这里解释并在这里提出的问题,UDP堆栈显然知道生成端口不可达的地址但它没有将该信息传递给调用者,因此没有什么可以做的就是将这些消息映射到有用的东西.您有可能在Vista之前运行Windows版本,并且UDP堆栈正在对该地址执行一些有用的操作,并且它将错误报告给正确的套接字,但不要在其上下注.

最后你还有问题; ICMP端口无法访问错误未能可靠地传递,因此如果您尝试将UDP数据发送到已消失的客户端,则无法确定是否会收到错误.恕我直言,这意味着你有时不应该依赖它.

您显然正在尝试在UDP之上构建某种面向连接的协议(为什么您的服务器会保留客户端的地址).你需要做更多的工作才能在UDP上建立一个可行的伪连接,首先要意识到的是,你知道客户端何时离开的唯一方法就是设置你自己的超时并"断开"你的如果您在一段时间内没有收到他们的声音,请进行伪连接.

当然这不能回答你的问题; 你怎么避免这个例外.我希望你不能.异常的原因可能是来自Recv()RecvFrom()调用的'失败'返回代码,而python网络代码可能会将所有此类失败返回转换为异常.



1> Len Holgate..:

首先,这可能是特定于平台的,您没有提到您正在运行的平台; 但是,10054是WSAECONNRESET如此我猜测某种Windows平台.

其次如前所述,与UDP无关.您Connect()在客户端中的呼叫只会导致客户端计算机上的网络代码允许您启动Send()呼叫而不是SendTo()呼叫,并且当您向Send()呼叫提供的地址发出呼叫时,只需将您发送数据的地址默认为Connect().

第三,我很惊讶你得到了WSAECONNRESET而不是ERROR_PORT_UNREACHABLE; 然而,潜在的原因可能是相同的.如果您要发送到的端口上没有打开套接字,则远程计算机上的UDP堆栈可能会发送ICMP端口无法访问错误.因此,如果您的客户端发送数据然后关闭套接字,然后您的服务器将数据发送回客户端地址,您将获得端口无法访问,并且某些版本的Windows可能会将其转换为连接重置错误...

这些ICMP端口无法访问错误的问题在于,它们是通过未通过UDP Recv/RecvFrom调用失败而通过Winsock代码报告的.正如我在这里解释并在这里提出的问题,UDP堆栈显然知道生成端口不可达的地址但它没有将该信息传递给调用者,因此没有什么可以做的就是将这些消息映射到有用的东西.您有可能在Vista之前运行Windows版本,并且UDP堆栈正在对该地址执行一些有用的操作,并且它将错误报告给正确的套接字,但不要在其上下注.

最后你还有问题; ICMP端口无法访问错误未能可靠地传递,因此如果您尝试将UDP数据发送到已消失的客户端,则无法确定是否会收到错误.恕我直言,这意味着你有时不应该依赖它.

您显然正在尝试在UDP之上构建某种面向连接的协议(为什么您的服务器会保留客户端的地址).你需要做更多的工作才能在UDP上建立一个可行的伪连接,首先要意识到的是,你知道客户端何时离开的唯一方法就是设置你自己的超时并"断开"你的如果您在一段时间内没有收到他们的声音,请进行伪连接.

当然这不能回答你的问题; 你怎么避免这个例外.我希望你不能.异常的原因可能是来自Recv()RecvFrom()调用的'失败'返回代码,而python网络代码可能会将所有此类失败返回转换为异常.

推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有