【问题标题】:Why is this python UDP socket getting reset to 'None'?为什么这个 python UDP 套接字被重置为“无”?
【发布时间】:2014-10-22 11:27:39
【问题描述】:

我编写了一些 python 代码来设置一个包含 udp 套接字的类UDPServer。我正在初始化套接字并将其绑定到 localhost 和构造函数中的特定端口。它报告成功。我有一个单独的成员函数来监听这个套接字上的传入数据。但它报告套接字为“无”。我的问题是为什么?如果我将套接字的初始化移出构造函数并进入侦听函数(即初始化和侦听都在一个函数中),则套接字不会变为“无”并且我能够在其上接收数据。

代码如下:

import socket

class UDPServer:
    def __init__(self, dst_ip, rcv_port, snd_port):
        self._dstip = dst_ip
        self._rcv_port = rcv_port
        self._snd_port = snd_port
        self._sock = self._create_socket()

    def _create_socket(self):

        # Create Datagram (udp) socket
        try :
            self._sock = socket.socket(socket.AF_INET, # Internet
                                       socket.SOCK_DGRAM) # UDP
            print 'Socket created.'
        except socket.error, msg :
            print 'Failed to create socket. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
            sys.exit()

        # Bind socket to local host and port
        try:
            self._sock.bind(("", self._rcv_port))
        except socket.error , msg:
            print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
            sys.exit()

        if(self._sock == None):
            print "self._sock is None after bind!!"

        print 'Socket bind complete.'

    def _receive_msg(self):     
        print "waiting on port:", self._rcv_port
        while True:
            if(self._sock == None):
                print "self._sock is None!"
            data, addr = self._sock.recvfrom(1024) # buffer size is 1024 bytes
            print "received message:", data     

def main():
    DST_IP = "100.1.11.275"
    UDP_RCV_PORT = 30001
    UDP_SND_PORT = 30002

    # Create UDP Server
    udpServer = UDPServer(DST_IP, UDP_RCV_PORT, UDP_SND_PORT)
    udpServer._receive_msg()

if __name__ == "__main__":
    main()

输出如下(我在 windows dos 提示符下运行):

d:\python_tests>python udp_server.py
Socket created.
Socket bind complete.
waiting on port: 30001
self._sock is None!
Traceback (most recent call last):
  File "udp_server.py", line 51, in <module>
    main()
  File "udp_server.py", line 48, in main
    udpServer._receive_msg()
  File "udp_server.py", line 38, in _receive_msg
    data, addr = self._sock.recvfrom(1024) # buffer size is 1024 bytes
AttributeError: 'NoneType' object has no attribute 'recvfrom'

d:\python_tests>

【问题讨论】:

    标签: python sockets udp


    【解决方案1】:

    _create_socket方法中,创建一个socket:

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    

    RETURN,这样__init__方法中的self._sock就会返回实际的袜子。 就目前而言,self._sock 被分配了 None 的值,因为如果没有指定其他值,那是函数的默认返回值。

    例如:

    def _create_socket(self):
    
            # Create Datagram (udp) socket
            try :
                sock = socket.socket(socket.AF_INET, # Internet
                                     socket.SOCK_DGRAM) # UDP
                print 'Socket created.'
            except socket.error, msg :
                print 'Failed to create socket. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
                sys.exit()
    
            # Bind socket to local host and port
            try:
                sock.bind(("", self._rcv_port))
            except socket.error , msg:
                print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
                sys.exit()
    
            if sock == None:
                print "sock is None after bind!!"
    
            print 'Socket bind complete.'
    
            return sock ### try this
    

    或者: 一开始就不要写self._sock = self._create_socket,你的代码就可以工作了。

    【讨论】:

    • 成功了,谢谢! ...但是为什么在该函数中修改实际成员 _sock 不起作用?
    • 如果没有指定其他值,Python中函数的默认返回值为None。所以你的函数返回 None,因此你的套接字是 None,因为 self._sock = self._create_socket() 有效地转换为 self._sock = None
    • 如果您在代码中遗漏了 'self._sock =' 的初始分配,创建套接字也会成功,因为在这种情况下您不会被分配 None
    【解决方案2】:

    在构造函数中,您将self._sock 分配给self._create_socket() 的返回值。问题是,self._create_socket() 不返回任何内容,或者更确切地说,它返回默认值 None

    如果你只是在原地更改self._sock,或者从函数中返回它,它就可以工作:

    import socket
    
    class UDPServer:
        def __init__(self, dst_ip, rcv_port, snd_port):
            self._dstip = dst_ip
            self._rcv_port = rcv_port
            self._snd_port = snd_port
            self._create_socket()
    
        def _create_socket(self):
    
            # Create Datagram (udp) socket
            try :
                self._sock = socket.socket(socket.AF_INET, # Internet
                                           socket.SOCK_DGRAM) # UDP
                print 'Socket created.'
            except socket.error, msg :
                print 'Failed to create socket. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
                sys.exit()
    
            # Bind socket to local host and port
            try:
                self._sock.bind(("", self._rcv_port))
            except socket.error , msg:
                print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
                sys.exit()
    
            if(self._sock == None):
                print "self._sock is None after bind!!"
            print 'Socket bind complete.'
    
        def _receive_msg(self):     
            print "waiting on port:", self._rcv_port
            while True:
                if not self._sock:
                    print "self._sock is None!"
                data, addr = self._sock.recvfrom(1024) # buffer size is 1024 bytes
                print "received message:", data     
    
    def main():
        DST_IP = "100.1.11.275"
        UDP_RCV_PORT = 30001
        UDP_SND_PORT = 30002
    
        # Create UDP Server
        udpServer = UDPServer(DST_IP, UDP_RCV_PORT, UDP_SND_PORT)
        udpServer._receive_msg()
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

    • 我明白了。是的,我退回了错误的东西。或者更确切地说,我在初始化后立即清除 self._sock。
    【解决方案3】:

    _create_socket(self) 不返回新创建的套接字,实际上该函数没有显式返回任何值。在 Python 中,如果没有遇到明确的 return 语句,函数将返回 None(并且该 return 语句本身并不返回 None)。在您的情况下,这意味着self._create_socket() 正在返回None,并且在您的__init__() 方法中将其分配给self._sock,从而覆盖self._create_socket() 中设置的值。

    所以,在__init__() 中,只需调用self._create_socket() 而不将返回值绑定到self._sock

    class UDPServer:
        def __init__(self, dst_ip, rcv_port, snd_port):
            self._dstip = dst_ip
            self._rcv_port = rcv_port
            self._snd_port = snd_port
            self._create_socket()
    

    【讨论】:

      猜你喜欢
      • 2013-04-13
      • 2018-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-05
      • 2013-12-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多