2014-10-22 97 views
1

我写了一些python代码,它设置了一个包含udp套接字的类UDPServer。我正在初始化套接字并将其绑定到本地主机和构造函数中的特定端口。它报告成功。我有一个单独的成员函数,然后侦听此套接字上的传入数据。但它报告套接字是'无'。我的问题是为什么?如果我将套接字的初始化从构造函数中移出并进入监听函数(即,init和listen全部在一个函数中),那么套接字不会变为“无”,并且我能够在其上接收数据。为什么这个python UDP套接字重置为'None'?

的代码如下:

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() 

输出是下面(我是从窗口运行此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> 

回答

1

在构造函数中,您将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() 
+0

我明白了。是的,我回来了错误的事情。或者说,我在初始化后立即清除self._sock。 – patchwork 2014-10-22 11:37:59

2

_create_socket方法中,创建套接字:

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

and RETURN它,这样self._sock中的__init__方法返回实际袜子。 因为它的原因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,你的代码将工作。

+0

奏效,谢谢! ...但为什么没有修改该函数内的实际成员'_sock'? – patchwork 2014-10-22 11:33:17

+0

如果没有指定其他值,则Python中函数的默认返回值为None。所以你的函数返回None,因此你的套接字是None,因为self._sock = self._create_socket()有效地翻译为self._sock = None – Totem 2014-10-22 11:40:56

+1

如果你遗漏了“self”的初始分配。_sock ='在你的代码中,创建套接字也会成功,因为在这种情况下,你不会将None分配给它 – Totem 2014-10-22 11:44:51

1

_create_socket(self)不会返回新创建的插座,实际上该函数不明确返回任何值。在Python中,如果没有遇到显式的返回语句(并且返回语句本身不返回None),函数会返回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()