【问题标题】:How do I check if a remote host is reachable at a specific port in C?如何检查远程主机是否可以在 C 中的特定端口访问?
【发布时间】:2015-07-26 00:57:51
【问题描述】:

我正在编写一个 C 程序来检查远程主机是否响应特定端口(在我的情况下,应用程序在远程端的 9090 上运行)。最初我尝试
nc -zv <host> <port> 使用 system() 函数调用,但无法获得所需的结果。 现在,我创建了一个非阻塞套接字并使用 connect() 调用来检查它。但它返回 -1 并设置 errno -115 (正在进行的操作) 在网上搜索后,我想到了使用select() 和poll(),但我不知道如何实现这些。 任何有关示例程序的建议都会有所帮助。

【问题讨论】:

    标签: c sockets


    【解决方案1】:

    做你正在做的事,但在阻塞模式下。

    否则,完全按照您的操作,然后将套接字 FD 添加到 writeFD​​s 集并调用 select(). 如果 FD 显示为可写,则连接成功。

    别忘了关闭套接字。

    但我想知道你为什么要这样做。只需尝试连接到您需要连接的任何东西,此时您需要这样做。不要试图预测它是否会成功。

    【讨论】:

    • 有什么方法可以为 connect() 调用指定超时时间。我的意思是 connect() 会在阻塞模式下尝试那么多秒
    • IIRC,connect() 超时是大多数操作系统上的系统范围参数,并假定对等方可能位于三个卫星链路和两个调制解调器后面(即,非常长:)。跨度>
    • @cbinder 否。您必须为此使用select()。请注意,您只能减少平台连接超时,而不能增加它。
    • 无法为connect() 指定超时。您必须在非阻塞模式下进行连接并使用select() 或(e)poll() 来检测超时/结果。
    • @EJP 到目前为止它工作正常,但现在阻塞模式下的 connect() 需要大约 20 秒才能返回无法访问的主机状态。我需要让它尽快返回。现在,当我使用 select() 并将超时设置为 0 时,它无法检测到连接(返回 0),而在设置超时时(我尝试了 5 秒)它可以工作。什么是安全值,还有其他方法吗?
    【解决方案2】:

    我的理解是,你只会做一个简单的连接。应该在 blockig 模式 中执行此操作。 这里举个例子:

    #include <netdb.h>
    #include <arpa/inet.h>
    #include <sys/un.h>
    
    in_addr_t in_build_addr(const char * p_server)
    {
      in_addr_t addr = inet_addr(p_server);
      if(INADDR_NONE == addr) {
        struct hostent * server_info = gethostbyname(p_server);
        if(NULL == server_info) {
          return 0;
        }
        memcpy(&addr, server_info->h_addr_list[0], server_info->h_length);
      }
      return addr;
    }
    
    int check_connect(const char * p_server, in_port_t p_port) {
      int sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
      if(0 > sock) {
        return -1;
      }
      struct sockaddr_in addr = {
          .sin_family       = AF_INET,
          .sin_port         = htons(p_port),
          .sin_addr.s_addr  = in_build_addr(p_server)
        };
      if(0 != connect(sock, (struct sockaddr *)&addr, sizeof(addr))) {
        close(sock);
        return -2;
      }
      close(sock);
      return 0;
    }
    

    您可以尝试使用_check_connect_功能。此函数连接到给定的服务器(ip 或名称)和端口并立即关闭套接字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-27
      • 1970-01-01
      • 1970-01-01
      • 2014-05-19
      • 2012-06-07
      • 2014-12-04
      • 1970-01-01
      相关资源
      最近更新 更多