Reputation: 1231
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
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
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
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