tcp eaddrnotavail

很久没来园子了,开年后一直忙于开发游戏的演示版本,今天发布了,一个值得庆祝的小日子:)给“码”年一个好的开局,也祝园子里的小伙伴们“码”年大吉,“码”上发大财,“码”出精彩!

 

游戏部署到阿里云服务器后,玩着玩着游戏桌子就会突然挂掉,查看日志发现错误{connection_error,eaddrnotavail}。我了个去,在深圳这么冷的春天给我和我的小伙伴们浇了一头冷水~~赶紧找虫子去,走查代码的走查代码,问古狗的古狗。。。在Erlang官网http://www.erlang.org/doc/man/inet.html上发现:

POSIX Error Codes

  • e2big - argument list too long
  • eacces - permission denied
  • eaddrinuse - address already in use
  • eaddrnotavail - cannot assign requested address

 

在调用TCP connect时,Linux内核会在某个范围内选择一个可用的端口作为本地端口去connect服务器,如果没有可用的端口可用,比如这个范围内的端口都处于如下状态中的一种:
1. bind使用的端口
2. 端口处于非TIME_WAIT状态
3. 端口处于TIME_WAIT状态,但是没有启用tcp_tw_reuse
那么就会返回EADDRNOTAVAIL错误。

 

一般情况下,出现这个错误应该是代码设计的问题:

1、我们在使用redis后,没有调用eredis:stop(Conn),所以在一段时间后没有可用的端口。

2、也没有使用连接池。

 

 

如果确定代码没有问题,那么根据上面的原则,可用使用如下方法解决问题:
1. 增大可选端口的范围,修改/proc/sys/net/ipv4/ip_local_port_range的值。
2. 开启tcp_tw_reuse,允许使用TIME_WAIT状态的端口。

 

posted @ 2014-02-19 17:56  hongmao  阅读(2210)  评论(0编辑  收藏  举报