2

ホストとそのポートをチェックするC関数があります。FQDNホスト名を使用すると、次のような関数がエラーを返します:connect()failed:connect timeout、しかし、代わりに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;
}
4

2 に答える 2

3

inet_pton()そのための間違ったタスクです。数値アドレスのみを受け入れます。

以前は、人々gethostbyname()は名前解決に使用していました。

しかし、2012年のように、この方法はまだに制限されているため、数年前から時代遅れになっていAF_INETます。

以下のプログラムを使用すると、ほぼ同じことを達成し、将来の互換性を維持する必要があります。

#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));
    }
}
于 2012-06-02T09:39:48.840 に答える
0

名前解決が機能していることを確認します。コードが実行されているのとまったく同じ環境から、名前でマシンにpingを実行できるかどうかを確認してください。

pingが機能する場合は、試してみてくださいtelnet <machinename> <portnumber> 。両方が機能する場合は、コードに問題がある可能性があります(これについては詳しく調べていませんが、あまりにも眠いです:)。

OSからIPアドレスとして返されたものをネットワークの順序からホストの順序に変換していることを確認してください。IIRC、gethostbynameは、ネットワーク順にバイナリIPアドレスを返します。

ntohlこれを達成するためにchksock.sin_addr.s_addr後に使用することができます。memcpy

于 2012-06-02T09:15:26.533 に答える