bind()与SO_REUSEADDR失败

时间:2011-11-30 18:13:39

标签: c sockets bind

我的任务是实现在通过TCP连接的两台计算机之间玩的双人游戏。其中一个要求是只有获胜者才能再次参加比赛。如果服务器获胜并决定不再进一步播放,则客户端应作为服务器重新启动并接受新连接。

我的方法: 如果游戏丢失(在客户端模式下),请关闭sockfd并重新创建另一个。然后使用setsockopt允许使用SO_REUSEADDR重新绑定,然后调用bind。

int yes = 1;
if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1 )
{
    perror("setsockopt");
}

if ( bind(sockfd, (struct sockaddr*)&svr, sizeof(svr) ) == -1 )
{
    perror("server: bind");
}

但是,我仍然得到相同的“地址已被使用”错误。在重新创建套接字之前,我已经尝试过休眠150秒,这种方法很有效。

注意:我在同一台PC上测试它。它可能适用于两台连接的PC,但必须使其在同一台PC上运行。请帮忙。

3 个答案:

答案 0 :(得分:2)

由于您在同一系统上运行此操作,因此听起来您有竞争条件。客户端在服务器关闭它之前尝试bind()套接字(假设服务器和客户端都在其套接字上设置SO_REUSEADDR。)

您需要实现某种握手,允许服务器在关闭侦听套接字后通知客户端 - 也许服务器应该在关闭上一个游戏中的活动套接字之前关闭侦听套接字?

答案 1 :(得分:1)

SO_REUSEADDR只允许您同时绑定到更多特定地址,即第一个服务器侦听INADDR_ANY(所有接口),后续服务器侦听不同的特定接口地址。

第二种情况是,当侦听TCP套接字接受连接时,该连接保持使用,但侦听套接字本身已关闭然后重新打开 - 说父服务器进程退出并重新启动。

在这两种情况下,在拨打SO_REUSEADDR之前,您需要在侦听套接字上始终设置bind(2)选项。

答案 2 :(得分:0)

设置此套接字选项允许本地地址重用。如果在尝试绑定到已关闭但未释放的端口时遇到问题(可能需要TIME_WAIT定义的最多2分钟)。应用SO_REUSEADDR套接字选项以立即释放资源并绕过TIME_WAIT状态。 0 =禁用,1 =启用。

允许其他套接字bind()到此端口,除非已有绑定到端口的活动侦听套接字。这使您可以在崩溃后尝试重新启动服务器时解决那些“已在使用中的地址”错误消息