2011-11-30 89 views
6

我的任务是实现在通过TCP连接的两台计算机之间播放的双人游戏。其中一个要求是只有获胜者可以选择再次参加比赛。如果服务器获胜并决定不进一步播放,客户端应该重新启动服务器并接受新的连接。与SO_REUSEADDR绑定()失败

我的方法: 如果游戏LOST(客户端模式),关闭的sockfd并重新创建一个又一个。然后使用setsockopt来允许使用SO_REUSEADDR重新绑定,然后调用绑定。

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上运行。请帮忙。

+2

请显示您的代码(特别是'setsockopt()'周围的部分),以便我们提供帮助。 –

+4

你确定在尝试在客户端代码中重新创建服务器端之前正确地关闭了服务器端(侦听套接字)?在Linux系统上,“netstat -tlp”应该确定哪些端口可以打开TCP侦听端口... – BRFennPocock

+0

您试图在同一台机器上绑定()同一个{address,portnum}两次?你期望会发生什么? – wildplasser

回答

2

因为你是在同一系统上运行此,它听起来就像你有一个竞争条件。在服务器关闭它之前,客户端正试图bind()套接字(假设服务器和客户端都在其套接字上设置了SO_REUSEADDR)。

您需要实现某种握手,允许服务器在关闭监听套接字后通知客户端 - 也许服务器应关闭监听套接字,然后关闭上一次游戏中的活动套接字。

+0

是的,插座关闭前有1秒的延迟,当我试图重新绑定时没有延迟。它现在工作得非常好! :) – tecfreak

1

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

第二种情况是,当监听TCP套接字接受连接,并将其存放在使用,但监听套接字本身被关闭,然后重新打开 - 说父服务器进程退出并重新开始。

在这两种情况下,您需要总是设置SO_REUSEADDR在收听套接字选项之前,请致电bind(2)

+0

那么..其他任何方法呢? 在两次调用之前,我正在使用SO_REUSEADDR。 – tecfreak

+0

这个选项通常用于避免在刚刚关闭的套接字处于TIME_WAIT状态时重新启动侦听特定端口的服务器时等待1-2分钟。 –

+0

是的,这是我的第二点。 –

0

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

允许其它套接字()绑定到这个端口,除非有绑定到端口已经活动侦听套接字。当您尝试在崩溃后重新启动服务器时,您可以绕过那些“Address already in use”错误消息