0

现在,我正在尝试setsockopt()使用以下代码指定选项:

// bind socket
// Use setsockopt() function to make sure the port is not in use
int yes = 1;
setsockopt(TCPSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
setsockopt(TCPSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
status = bind(TCPSocket, host_info_list->ai_addr, host_info_list->ai_addrlen);
if (status == -1)  std::cout << "bind error" << std::endl ;

// listen for connections
status =  listen(TCPSocket, 5);
if (status == -1)  std::cout << "listen error" << std::endl ;

int new_sd;
struct sockaddr_storage their_addr;
socklen_t addr_size = sizeof(their_addr);
new_sd = accept(TCPSocket, (struct sockaddr *)&their_addr, &addr_size);
if (new_sd == -1) std::cout << "listen error" << std::endl ;

注意tv是一个已经指定的时间。

当我只打第一个setsockopt()电话时,一切正常。但是,添加第二个(不返回任何错误)后,我遇到了代码中指定的第二个“监听错误”。我不确定为什么设置超时值会影响这一点,有人可以解释一下吗?

我不相信指定的代码;它是根据此处教程中提供的代码修改的:http: //codebase.eu/tutorial/linux-socket-programming-c/

4

2 回答 2

2

如果您看到这样的 TCP 状态图TIME_WAIT您会看到主动关闭套接字时调用的状态。根据RFC793 ,此状态可能需要一些时间才能结束,最多四分钟。

当套接字处于等待状态时,TIME_WAIT您不能使用与处于等待状态的套接字相同的地址端口对绑定到接口。SO_REUSEADDR当当前套接字(设置了标志)处于该TIME_WAIT状态时,设置一个套接字的标志可以使其他套接字绑定到该地址。

SO_REUSEADDR选项对服务器(被动、侦听)套接字最有用。


至于您的问题,在每次调用后setsockopt检查它返回的内容,如果是,-1那么您检查一下errno出了什么问题。您可以使用perrororstrerror打印或获取错误的可打印字符串,例如

if (setsockopt(TCPSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0)
{
    std::cerr << "Error setting the SO_REUSEADDR: " << strerror(errno) << '\n';
    // Do something appropriate
}
于 2015-11-23T06:57:03.457 回答
0

Joachim 的解决方案在回答我最初的问题和解释 setsockopt() 方面做得很好。在意识到问题在代码中更进一步之后回答我自己的问题,超时会影响服务器能够监听端口。假设超时只有10ms,必须启动服务器,然后启动客户端,并且必须在那个时间内建立连接。这在我的情况下没有发生,因此导致了错误。

于 2015-11-23T07:20:39.123 回答