检查指定主机上的端口是否打开

时间:2020-06-01 17:02:58

标签: c linux unix networking network-programming

我正在尝试查找给定主机中的端口是打开还是关闭。我不知道这是否是正确的方法。在这里,我只检查0到1024之间的端口。有人可以说这是否正确,因为我的大多数端口都是关闭的,而有些端口只是打开的,还有什么方法可以打印端口名称,例如端口号是80时,端口名称是HTTP。


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

char *convert_int_to_string(int num)
{
    int tmp;
    int i = 0;
    int j = 0;
    static char a[5] = {'0'};

    while (num > 0) {
        tmp = num % 10;
        a[i++] = tmp + '0';
        num = num / 10;
    }
    a[i] = '\0';
    for (j = 0; j < i / 2; j++) {
        tmp = a[j];
        a[j] = a[i - j - 1];
        a[i - j - 1] = tmp;
    }
    return a;
}


int main(int argc, char **argv)
{
    int status;
    char *node;
    char *port_no;
    int sock_fd;
    int i = 0;
    struct  addrinfo hints, *serviceinfo;

    if (argc != 2)
        error(1, errno, "Too many or few arguments\n");
    node = argv[1];
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    for (i = 0; i < 1024; i++) {
        port_no = convert_int_to_string(i);
        status = getaddrinfo(node, port_no, &hints, &serviceinfo);
        if (status != 0) {
            error(1, errno, "error in getaddrinfo() function call\n");
        }
        sock_fd = socket(serviceinfo->ai_family, serviceinfo->ai_socktype, serviceinfo->ai_protocol);
        if (sock_fd == -1)
            error(1, errno, "error in socket() function call\n");
        status = connect(sock_fd, serviceinfo->ai_addr, serviceinfo->ai_addrlen);
        if (status != -1)
            printf("Port : %s is open\n", port_no);
        else
            printf("Port : %s is closed\n", port_no);
    }
}

1 个答案:

答案 0 :(得分:1)

如果您只想检查TCP端口而不是UDP,我建议您简单地尝试将connect()连接到服务器并等待一段时间,然后再假设该端口已关闭。

您必须使用poll()或select()才能使connect()调用超时。 (C: socket connection timeout

这是一个可行的示例: (仅适用于IP,不适用于域名,因此您必须ping服务器以查找其IP地址或自己实现dns查询)

#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <unistd.h>


#define MAX_PORT 1024
#define TIMEOUT 5000

int main(int argc, char *argv[])
{
    struct sockaddr_in addr = {
        .sin_family = AF_INET,
        .sin_addr.s_addr = inet_addr(argv[1])
    };
    struct pollfd fds[1];

    for (uint16_t port = 0; port < MAX_PORT; port++) {
        int8_t sock = socket(PF_INET, SOCK_STREAM, 0);
        fcntl(sock, F_SETFL, O_NONBLOCK);
        fds[0].fd = sock;
        fds[0].events = POLLOUT;
        addr.sin_port = htons(port);

        if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
            if (errno == EINPROGRESS) {
                if (poll(fds, 1, TIMEOUT) > 0)
                    printf("Port %d opened.\n", port);
                else
                    printf("Port %d closed.\n", port);
            }
            else
                printf("Port %d closed.\n", port);
        }
        else
            printf("Port %d opened.\n", port);
        close(sock);
    }
}