21

If I want to accept a connection I call accept, but how can I refuse a connection?

In a working socket echo client I have this if statement. In the echo server, how can I make the echo client reach this printf statement?

...
if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { 
    printf("Connecting failed\n"); 
    return 1; 
}
...
4

5 回答 5

13

要获得您想要的行为(一次只接受一个连接,其他尝试的客户端应该会失败),有两种选择。

  • 接受连接后,您可以关闭侦听套接字。在接受的连接关闭后重新创建您的侦听套接字。

  • 如果已经有一个正在进行的连接,您可以关闭新建立的连接。如果您希望客户端看到 TCP 重置,如果您启用超时为 0 的 linger 选项,大多数 TCP 堆栈都会触发一次。

    struct linger lo = { 1, 0 };
    setsockopt(s, SOL_SOCKET, SO_LINGER, &lo, sizeof(lo));
    close(s);

于 2013-05-16T15:20:45.850 回答
8

据我所知,这不是 TCP 的工作方式。呼叫将accept(..)始终返回客户详细信息。没有办法窥视连接并选择性地拒绝。

你现在这样做的方式实际上是正确的方式:接受然后关闭。如果您在此层之上有另一个消息结构,您可以创建自定义“拒绝消息”。此选项完全取决于您的用例。

如果您正在寻找基于 IP 地址的拒绝,它不在您的应用程序域内。它是你的防火墙的工作(正如@Bart Friederichs 所说)。这样,请求甚至不会触及 TCP 堆栈。


实际上,我只想在这个特定端口上严格建立一个连接。理想情况下,任何其他连接都应该以非常明显的方式失败。

不要让 accept 调用在您的控制流中。只有当您等待时,accept您的程序才会等待套接字连接,否则不会。

于 2013-05-16T15:08:40.943 回答
5

在大多数平台上的标准套接字 API 中,没有办法拒绝连接。accept()如果您不想要它,您必须连接,然后立即关闭它。

此规则的例外是特定于 Winsock 的WSAAccept()函数。它提供了一个回调,允许应用程序根据每个连接决定是否应该接受、拒绝连接或将连接保留在积压队列中。

于 2013-05-16T20:47:28.417 回答
2

这可能会有所帮助

  1. 在成功accept()连接客户端连接后关闭侦听服务器套接字,并且
  2. 在客户端连接由于某种原因而消失后重新建立它。
于 2013-05-16T15:12:40.297 回答
1

聚会有点晚了,但是您可以使用 WSAAccept() 而不是 accept()。WSAAccept() 有一个可选的回调函数,它允许您查看谁在敲门并决定是否要回答。您的回调函数可以返回常量 CF_ACCEPT、CF_REJECT 和 CF_DEFER。前两个很明显。第三个允许您推迟回答,以防您稍后需要决定。一旦你确定你再次调用 WSAAccept() 并接受或拒绝。

不幸的是,您必须接受或拒绝才能从侦听队列的前面删除条目。我说这很不幸的原因是连接机器在被拒绝和从未得到响应(超时)之间存在明显差异。

如果黑客使用端口扫描器,如果您拒绝,他们就会知道您正在侦听端口。到那时,他们就可以开始入侵了。如果能够从队列的前面删除条目而不用做任何事情,这样在另一端的人都不知道你在听,那就太好了那个港口。

于 2019-02-05T20:19:08.980 回答