我的任务是实现通过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 =启用
允许其他套接字绑定()到该端口,除非已经有一个活动侦听套接字绑定到该端口。这使您能够绕过那些"地址已经在使用"的错误信息,当你试图重启你的服务器崩溃后