patchwork
patchwork

Reputation: 1231

Why is this python UDP socket getting reset to 'None'?

I have written some python code that sets up a class UDPServer containing a udp socket. I'm initialising the socket and binding it to localhost and a particular port in the constructor. It reports success. I have a separate member function to then listen out for incoming data on this socket. But it reports that the socket is 'None'. My question is why? If I move the initialisation of the socket out of the constructor and into the listening function (i.e. the init and listening is all in one function), the socket does not become 'None' and I am able to receive data on it.

The code is as follows:

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

The output is below (I'm running this from windows dos prompt):

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>

Upvotes: 1

Views: 1166

Answers (3)

Totem
Totem

Reputation: 7369

In the _create_socket method, create a socket:

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

and RETURN it, so that self._sock in the __init__ method is returned the actual sock. As it stands self._sock is assigned the value of None, because the that is the default return value of a function, if no other value is specified.

Ex:

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

Alternatively: Do not write self._sock = self._create_socket in the first place, and your code will work.

Upvotes: 2

mhawke
mhawke

Reputation: 87134

_create_socket(self) does not return the newly created socket, in fact the function does not explicitly return any value. In Python, functions return None if no explicit return statement is encountered (and that return statement does not itself return None). In your case, this means that self._create_socket() is returning None and this is being assigned to self._sock in your __init__() method, overwriting the value that was set in self._create_socket().

So, in __init__(), just call self._create_socket() without binding the return value to 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()

Upvotes: 1

danny
danny

Reputation: 5270

In the contructor you are assigning self._sock to the return value of self._create_socket(). Problem is, self._create_socket() does not return anything, or rather it returns the default value of None.

If you just change self._sock in place, or return it from the function, it works:

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

Upvotes: 1

Related Questions