来源
在开发一个利用安卓代理 service实现类似于防火墙的功能的时候,外网获得数据,然后重新从向代理的File channel写入的时候,报错No buffer space available,换成FileOutputStream调用write的时候,错误变成了ENOBUFS,而且出现时机不定,都是在channel准备写入特别大的bytebuffer的时候出现的(一般都是2w+、3w+ bytes出现的),或者做大批量下载、网速测试的时候。
坑
在谷歌上搜了一天查了一天文档,看到N多都是在写java的服务器的时候,http发送过多但是没有及时关闭,造成socket链接数量超过系统限制,或者socket没有及时清空缓存造成的,于是乎在adb shell,调用
cat /proc/net/sockstat
发现socket数量在增加,但是如果不大批量测试就会回归正常。这也是导致我一直以为真的是谷歌上搜到的那些人一样情况的原因,尽管他们是开发的服务器应用。所以我考虑会不会是安卓底层限制。
爬坑
后来经过一整天的编译、测试、编译、测试,发现如果修改socket的收包缓冲区大小,小于32kB就基本不会出现这个问题,然后翻阅了一遍其他人写的代理 firewall源码,其中一个项目的读包的buffer是设置的8kB,恍然大悟,多次测试发现,低于30kB,就基本不会出现这个问题了
总结
no buffer space available还是要从字面上理解,不能光看谷歌,没有缓冲区可用,那肯定是和缓冲区有关,如果socket连接量过大,也应该会导致buffer不可用,所以应在buffer大小上测试,最终得出来结论,就是buffer设置太大了,改为16KB就稳定了不会出现这个问题了。