C# 打开的文件太多(Ubuntu上的Mono.NET)

C# 打开的文件太多(Ubuntu上的Mono.NET),c#,.net,ubuntu,mono,C#,.net,Ubuntu,Mono,我知道有很多这样的问题,但我看不到任何符合我的具体情况 我正在Ubuntu上通过Mono运行一个.NET控制台应用程序。该应用程序作为服务器运行,并通过TcpListener(TcpListener.AcceptTcpClient())接受连接。我的问题是,过了一段时间,程序开始抛出“太多打开的文件”异常 我已经在我知道的两个地方增加了Ubuntu中的最大文件限制: /etc/security/limits.conf root软文件240000 root硬文件320000 (正在讨论的进程以

我知道有很多这样的问题,但我看不到任何符合我的具体情况

我正在Ubuntu上通过Mono运行一个.NET控制台应用程序。该应用程序作为服务器运行,并通过TcpListener(TcpListener.AcceptTcpClient())接受连接。我的问题是,过了一段时间,程序开始抛出“太多打开的文件”异常

我已经在我知道的两个地方增加了Ubuntu中的最大文件限制:

  • /etc/security/limits.conf
root软文件240000

root硬文件320000

(正在讨论的进程以root用户身份运行)

  • /etc/sysctl.conf
fs.file-max=2000000

两者都设置为20万左右

如果检查系统上打开的文件描述的数量,即使抛出错误,也只有996个

我在几个连接更多的Windows服务器上运行同一个程序,它们从来没有出现过这个问题


知道是什么导致了这个错误吗?

在linux中,TCP连接被分配了一个文件句柄,这可能就是为什么它显示了太多打开的文件句柄。完成TCP连接后,是否要关闭它们?显示该问题的代码示例会有所帮助。

在Windows上不发生错误的原因可能与垃圾收集完成的时间有关。如果未显式关闭套接字连接,则在收集套接字时将关闭它们

这有点推测性,但如果Mono在看到内存耗尽且从不耗尽内存之前不启动垃圾收集,则永远不会关闭套接字。Windows.NET framework可能会定期运行垃圾收集,或者在发现文件描述符用完时运行垃圾收集,这可能是造成差异的原因


作为测试,您可以定期强制执行手动垃圾收集(GB.Collect),如果这可以修复错误,正确的解决方案是不依赖垃圾收集来关闭套接字,确保在代码中手动关闭它们。强制手动垃圾收集会带来一系列问题。

您尝试过将ulimit设置为root吗

在某些发行版上,以下功能可能有效:

检查ulimit:

Command: sudo ulimit -n
Response: 1024
Command: sudo ulimit -n
Response: 65500
设置ulimit:

Command: sudo ulimit -n 65500
重新启动

检查ulimit:

Command: sudo ulimit -n
Response: 1024
Command: sudo ulimit -n
Response: 65500
我自己对“UbuntuPrecise”的测试返回了一个错误,说明找不到命令。
但是,以下方法对我有效(当通配符对普通用户不起作用时,用实际用户名替换“user”)

我第一次遇到类似的问题,但我就是这样做的:

sysctl -w net.inet.ip.portrange.first=3000  
sysctl -w net.inet.ip.portrange.hifirst=3000  
sysctl -w kern.maxfiles=900000  
sysctl -w kern.maxfilesperproc=900000  
ulimit -n 900000  
我在root而不是普通用户(不同的软限制)下运行该进程,并设法创建了多达100000个连接。请注意,ulimit绑定到一个shell,因此需要在与ulimit相同的shell中输入mono(yourapp.exe),而不是从MonoDevelop输入


用于在OSX 10.7.5下运行的开发。

您能粘贴更改的配置文件的相关部分吗?对于正在运行应用程序的用户,该限制看起来仍然是默认的1024。另外请注意,据我所知,新的限制仅在新登录后生效。erm。。好像有什么东西丢了。此外,请通过编辑问题而不是在评论中提供所有信息。谢谢:)据我所知,应用程序故意使用了1024个以上的同时连接。非常重要-将“会话所需pam_limits.so”添加到/etc/pam.d/common-session垃圾收集与套接字有什么关系?GC是关于托管内存的。@AndrewBarber GC调用所收集的每个类的Finalize()方法。具有非托管资源的类通常实现IDisposable模式,添加一个Dispose()方法来清理非托管句柄。这些类中的终结器通常调用Dipose()方法。因此,当用户自己从不调用Dispose(这是一种非常糟糕的做法)并且GC从不收集时,则从不调用Dispose,也从不收集非托管资源。@drake7707这实际上是一个很好的观点,现在发布该评论让我有点尴尬!