Python Socket 报错 "[Errno 24] 打开文件太多
我有一个UDP类,每秒大约发送100次数据数组。
from six import string_types
import socket
import struct
def convert_data(iterable):
if isinstance(iterable, string_types):
return str(iterable)
data = tuple(iterable)
format = "{0}H".format(len(data))
print("Sending data:", format, data)
if max(data) > 2**16 - 1:
raise ValueError(max(data))
if min(data) < 0:
raise ValueError(min(data))
return struct.pack(format, *data)
class UDP(object):
def __init__(self, ip, port):
self._ip = ip
self._port = port
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.connect((ip, port))
def send_data(self, data):
message = convert_data(data)
return self.socket.sendall(message)
大约发送了一分钟后,它出现了以下错误,尽管之前发送成功了:
Traceback (most recent call last):
File "take_analogue_data.py", line 13, in <module>
File "take_analogue_data.py", line 8, in main
File "/home/pi/nio-integration/hardware/raspi/UDP.py", line 22, in __init__
File "/usr/lib/python2.7/socket.py", line 187, in __init__
socket.error: [Errno 24] Too many open files
我找过解决办法。这个Stack Overflow的回答建议增加可以打开的文件数量。不过我觉得这并不是我想要的解决方案。
我能做些什么呢?我在想每次关闭连接可能会有效,但我已经尝试过很多方法了。(我试过了send
、sendall
和sendto
,都没有成功。)
注意:我在树莓派上运行的是Python2.6和Raspbian Wheezy。
编辑 另一个模块正在发送数据。它可能看起来像这样:
import UDP
udp = UDP.UDP(IP, PORT)
while(True):
udp.send_data(range(8))
sleep(0.01)
2 个回答
1
class UDP(object):
def __init__(self, ip, port):
self._ip = ip
self._port = port
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.socket.connect((ip, port))
你需要知道的是,UDP是一种无会话和无连接的协议。这意味着你不能使用self.socket.connect((ip,int(port)))
这样的方式去连接,所以你应该把它去掉。
如果你想要连接到一个服务器,应该使用TCP协议:
class TCP(object):
def __init__(self, ip, port):
self._ip = ip
self._port = port
self.socket = socket.socket() #Here is the change
self.socket.connect((ip, port))
def send_data(self, data):
message = convert_data(data)
return self.socket.sendall(message)
希望这对你有帮助!
7
很可能,你在每次循环 while(True):
的时候都在创建一个新的套接字。每个进程能打开的文件描述符数量是有限的(套接字也是文件描述符)。你可以查看 /etc/security/limits.conf
文件,看看你的限制设置是什么。
当你用完套接字后,应该把它关闭,或者更理想的做法是只打开一个套接字,然后尽量重复使用它。
你提到你的其他模块“可能看起来像这样”。那段代码片段真的是这样吗?
我对此表示怀疑,因为如果是这样的话,应该只会创建一个套接字。如果你在 while
循环里面实例化 UDP 对象,那么上面提到的问题肯定就是你的麻烦所在。