当端口关闭时,使用套接字检查远程服务器上的开放端口是否挂起

时间:2016-12-04 13:24:08

标签: c sockets

我写了一个简单的应用程序,它连接到给定端口上的给定服务器。当端口打开时,一切正常,我收到有关已建立连接的消息。但是,当端口关闭时,没有任何反应,我的程序没有向我显示有关它的信息。

我使用可通过Internet访问的远程服务器测试我的程序。我怎样才能改善这个?

#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: ./canconnect ip port\n");
        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);

    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
    {
        perror("connect");
        printf("Port %d is closed on server %s.\n", port, ip_addr);
        exit(1);
    }
    else
    {
        printf("Connection established. Port %d is open on server %s.\n", port, ip_addr);
    }

    close(sockfd);

    return 0; }

2 个答案:

答案 0 :(得分:2)

鉴于该程序在一段时间后实际打印了一些数据,它肯定与 timeout 有关。

为了最终确定主机或端口不可读或由于任何其他原因无法建立连接,connect会执行多次连接尝试并在一定数量的情况下返回错误时间 - 超时

超时值可以使用setsockopt更改为您想要的任何值:

struct timeval timeout;      
timeout.tv_sec = 3; // wait for three seconds
timeout.tv_usec = 0;

// set up receive timeout
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
            sizeof(timeout)) < 0)
    printf("[!] setsockopt failed\n");

答案 1 :(得分:1)

如果远程服务器可以访问,但既不接受也不拒绝连接,则connect()将阻塞,直到网络连接尝试超时。正如the Linux manual page for connect(2)所说:

  

请注意,对于IP套接字,当在服务器上启用syncookies时,超时可能会很长。

实际上,对于端口扫描而言,这是众所周知的防御措施,试图故意引发这种行为。通过使用setsockopt()设置接收超时,您可能会更快地失败,但是文档在是否适用于connect()时不一致。