检查C中端口可达

标签 c networking tcp ip-address hostname

我有一个 C 函数来检查主机及其端口,当我使用 FQDN 主机名时,该函数返回错误,例如:connect() failed: connect time out,但如果我使用 IP 地址,则似乎没问题,如何解决这个问题?

谢谢。

#include <unistd.h>
#include <string.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>

int is_network_up(char *chkhost, unsigned short chkport) {
    int sock;
    struct sockaddr_in chksock;
    struct hostent *host = NULL;

    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
        syslog(LOG_ERR, "socket() creation error: %s", strerror(errno));
        return 0;
    }

    memset(&chksock, 0, sizeof(chksock));
    chksock.sin_family = AF_INET;
    chksock.sin_port = htons(chkport);

    /* get the server address */
    if (inet_pton(AF_INET, chkhost, &(chksock.sin_addr.s_addr)) <= 0) {
        if ((host = gethostbyname(chkhost)) == NULL) {
            syslog(LOG_ERR, "%s", hstrerror(h_errno));
            return 0;
        }

        memcpy(&(chksock.sin_addr.s_addr), &(host->h_addr_list[0]),
               sizeof(struct in_addr));
    }

    /* try to connect */
    if (connect(sock, (struct sockaddr *) &chksock, sizeof(chksock)) < 0) {
        syslog(LOG_ERR, "connect() failed: %s", strerror(errno));
        return 0;
    }

    close(sock);
    return 1;
}

最佳答案

inet_pton() 是错误的任务。它只接受数字地址。

以前,人们习惯使用 gethostbyname() 进行名称解析。

但随着 2012 年的到来,这种方法已经过时好几年了,因为它仍然仅限于 AF_INET

通过下面的程序,您应该实现大致相同的目标并保持 future 的兼容性。

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>

int is_network_up(char *chkhost, unsigned short chkport) {
    int sock = -1;
    struct addrinfo * res, *rp;
    int ret = 0;
    char sport[10];
    snprintf(sport, sizeof sport, "%d", chkport);

    struct addrinfo hints = { .ai_socktype=SOCK_STREAM };

    if (getaddrinfo(chkhost, sport, &hints, &res)) {
        perror("gai");
        return 0;
    }

    for (rp = res; rp && !ret; rp = rp->ai_next) {
        sock = socket(rp->ai_family, rp->ai_socktype,
                rp->ai_protocol);
        if (sock == -1) continue;
        if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) {
            char node[200], service[100];
            getnameinfo(res->ai_addr, res->ai_addrlen, node, sizeof node, service, sizeof
service, NI_NUMERICHOST);

            printf("Success on %s, %s\n", node, service);
            ret = 1;                  /* Success */
        }
        close(sock);
    }
    freeaddrinfo(res);

    return ret;
}

int main(int argc, char** argv) {
    if (argc > 1) {
        printf("%s: %d\n", argv[1], is_network_up(argv[1], 22));
    }
}

关于检查C中端口可达,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10860985/

相关文章:

c - 我需要一个将二维数组传递给 C 函数的简单示例

java - Java 中的网络/在线应用程序

linux - 尝试发送带有数据的 TCP SYN 数据包和带有数据的 RST,但原始数据字段在传输过程中消失。为什么?

Linux:如何在给定套接字描述符的情况下获取 TCP 套接字选项?

java - 如何让本地多人java游戏在线运行?

c - 为什么 strtof 和 strtod 的 endptr 参数是指向非 const char 指针的指针?

c - 读取文件并将相同内容保存到新文件中,但不包含文件中的注释

C: thread_mutex 同步

linux - 监听机器上的每个端口

linux - 如果很多socket连接处于TIMEWAIT状态,是否会影响服务器的性能