使用SO_REUSEADDR的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上运行。请帮助。

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

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

在这两种情况下,你需要总是设置SO_REUSEADDR选项在监听套接字之前调用bind(2)

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

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

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

允许其他套接字绑定()到该端口,除非已经有一个活动侦听套接字绑定到该端口。这使您能够绕过那些"地址已经在使用"的错误信息,当你试图重启你的服务器崩溃后

相关内容