为什么这个Python UDP套接字会被重置为'None'?
我写了一些Python代码,创建了一个叫做UDPServer
的类,这个类里面有一个UDP套接字。在构造函数里,我初始化了这个套接字,并把它绑定到本地地址和一个特定的端口。这个步骤报告说成功了。然后我有一个单独的成员函数,用来监听这个套接字上是否有数据进来。但是它报告说这个套接字是'None'。我的问题是为什么会这样?如果我把套接字的初始化从构造函数中移到监听函数里(也就是说初始化和监听都放在一个函数里),那么套接字就不会变成'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()
输出结果如下(我是在Windows的命令提示符下运行的):
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>
3 个回答
_create_socket(self)
这个函数并没有返回新创建的套接字,实际上这个函数并没有明确返回任何值。在Python中,如果一个函数没有遇到明确的返回语句,它会默认返回 None
。在你的情况中,这意味着 self._create_socket()
返回的是 None
,而这个 None
被赋值给了 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()
在 _create_socket
这个方法里,创建一个套接字:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
然后返回这个套接字,这样在 __init__
方法里,self._sock
就能得到实际的套接字。现在的情况是,self._sock
被赋值为 None
,因为如果函数没有返回其他值,默认返回的就是 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
,这样你的代码就能正常工作了。
在构造函数里,你把 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()