2014-10-22 92 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()