如何检查远程UDP端口是否打开? C

时间:2017-03-01 19:02:15

标签: c sockets udp

测试TCP很容易,但UDP怎么样?在这里:Check if OpenVPN UDP Port is open我读到这是不可能的。但是,在这里:How to retrieve both TCP and UDP ports with Nmap?证明了nmap可以做到这一点,所以我认为可能。

我写了一个非常简单的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    char * ip_addr;
    int port;

    int sockfd;
    struct sockaddr_in server_addr;

    if (argc != 3)
    {
        fprintf(stderr,"Usage: %s IP port \n", argv[0]);
        exit(1);
    }

    ip_addr = argv[1];
    port = atoi(argv[2]);

    if (port <= 0)
    {
        fprintf(stderr,"error: invalid port\n");
        exit(1);
    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(1);
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    inet_aton(ip_addr, &server_addr.sin_addr);

    char msg[] = "Just a text\n";
    char buffer[255];
    int recv_size, send_size;

    if ((send_size = sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*) &server_addr, sizeof(server_addr))) < 0)
    {
        close(sockfd);
        if (errno != 0)
        {
            perror("send");
            exit(1);
        }
    }else if(send_size == 0)
    {
        printf("sent\n");
    }
    else if (send_size > 0)
    {
        printf("sent\n");
    }

    if ((recv_size = recvfrom(sockfd, buffer, 255, 0, NULL, NULL)) == 0)
    {
        close(sockfd);
        if (errno != 0)
        {
            perror("recv");
            exit(1);
        }
    }

    buffer[recv_size] = '\0';

    close(sockfd);


    return 0;
}

但它没有打印,只是结束。如果端口是否打开,很难说明发生了什么。是否有一种简单的方法,使用套接字来测试远程UDP端口是否打开?

2 个答案:

答案 0 :(得分:2)

  

测试TCP [正在打开的端口]很容易,但UDP怎么样?

无法可靠地检测到任何一种风味的远程端口已关闭。甚至无法可靠地检测到远程TCP端口打开 - 您可以做的最好的事情是通过成功连接到来确定该端口是否已打开 它。即使远程计算机接受来自不同计算机的连接,它也可以肯定地拒绝您的连接尝试,并且它可以默默地忽略该端口是打开(到其他计算机)还是关闭的尝试。

所有这些也适用于UDP,除非你不能依赖远程机器的响应,即使它接受你的数据包。你可能得到肯定的拒绝,但如果你不这样做,你就不会从这次尝试中学到任何东西。您可以在远程端口上扫描从您的计算机上运行和提供请求的特定UDP服务,但是您无法更准确地计算端口是否已打开。

答案 1 :(得分:0)

您的套接字是使用SOC_STREAM创建的,但从未连接过。在这种情况下sendto失败并显示ENOTCONN。代码不会打印,因为close(sockfd)成功并将errno重置为0。

另请注意,您不需要测试errno; sendto失败后保证不为零:

    if ((send_size = ....) < 0) {
        perror("send");
        close(sockfd);
        ....
    }