“bind failed on XXXX: Address already in usr”问题

今天调试一个http服务的时候,发现服务重启时,会报“bind failed on XXXX: Address already in usr”错误,应该是上次socket资源还在占用未释放(TCP处于TIME_WAIT状态)。后来查看了服务启动的相关代码,发现代码设计时已经是考虑了上述问题的,而且还在两处尝试解决该问题,不过代码里有点小bug,需要纠正一下。

代码中第一处尝试解决服务重启后端口复用问题,在准备启动服务时:

    fprintf( fp, "echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse\n");
    fprintf( fp, "httpd >> /tmp/httpd.log 2>&1 &\n" );
    fprintf( fp, "sleep 2\n" );
    fprintf( fp, "echo 0 > /proc/sys/net/ipv4/tcp_tw_reuse\n");

代码中第二处尝试解决服务重启后端口复用问题,在bind端口时:

GIOChannel *http_bind_socket( const char *ip, int port, int queue ) 
{
    struct sockaddr_in addr;
    int fd, r, n = 1;

    addr.sin_family = AF_INET;
    addr.sin_port   = htons(port);
    r = inet_aton( ip, &addr.sin_addr );
    if (r == 0)
    {
        g_error("inet_aton failed on %s: %m", ip);	
    }
	
    fd = socket( PF_INET, SOCK_STREAM, 0 );
    if (r == -1)
    {
        g_error("socket failed: %m");	
    }
    r = bind( fd, (struct sockaddr *)&addr, sizeof(addr) );
    if (r == -1)
    {
        g_error("bind failed on %s: %m", ip);	
    }
    r = setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n) );
    if (r == -1)
    {
        g_error("setsockopt failed on %s: %m", ip);	
    }
上述代码中setsockpt操作在bind之后,已经无法及时生效,因此,需要调整为

GIOChannel *http_bind_socket( const char *ip, int port, int queue ) 
{
    struct sockaddr_in addr;
    int fd, r, n = 1;

    addr.sin_family = AF_INET;
    addr.sin_port   = htons(port);
    r = inet_aton( ip, &addr.sin_addr );
    if (r == 0)
    {
        g_error("inet_aton failed on %s: %m", ip);	
    }
	
    fd = socket( PF_INET, SOCK_STREAM, 0 );
    if (r == -1)
    {
        g_error("socket failed: %m");	
    }
    r = setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n) );
    if (r == -1)
    {
        g_error("setsockopt failed on %s: %m", ip);	
    }
    r = bind( fd, (struct sockaddr *)&addr, sizeof(addr) );
    if (r == -1)
    {
        g_error("bind failed on %s: %m", ip);	
    }
下面是截取自博文http://blog.csdn.net/hbhhww/article/details/7751838中截取:
    如果端口复用了(设置了socket的SO_REUSEADDR选项),在一个应用程序可以把n个套接字绑在一个端口上而不出错。那现在是不是可以从这些套接字中并发地读取了?答案是否定的——测试结果是只有最后一个套接字会正常接收数据。
    端口复用最常用的用途是防止服务器重启时之前绑定的端口还未释放。这种情况下如果设定了端口复用,则新启动的服务器进程可以直接绑定端口,直接接过前辈的枪。如果没有设定端口复用,绑定会失败,提示ADDR已经在使用中——那只好等等再重试了,麻烦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值