端口全连接扫描程序(Linux, socket):TCP的connect方式

  • 时间:
  • 来源:互联网

TCP建立连接需要使用三次握手协议。在Linux下的socket API,服务器使用socket, bind, listen, accept的过程打开并且监听端口,客户端使用socket,bind(可有可不有),connect的过程连接到服务器的某一个端口。当客户端要连接的服务器的端口开放,客户端利用connect可以通过三次握手协议正常建立连接。当客户端要连接的服务器的端口关闭,客户端connect到服务器的时候,服务器响应RST,客户端connect返回ECONNREFUSED错误。可以通过这个连接是否成功来判断端口是否打开。以下是端口扫描代码:


#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define MAXLINE 4098

int main(int argc, char **argv)
{
  int sockfd, n;
  struct sockaddr_in servaddr;

  //input the IP address and port(from argv[2] to argv[3])
  if (argc != 4) {
    printf("usage: fulfill the cmd\n");
    return -1;
  }

  int i;
  //atoi():char* to int
  for (i = atoi(argv[2]); i < atoi(argv[3]); i++) {
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
      printf("socket error\n");
      return -1;
    }

    //include in string.h
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(i);
    //inet_pton include in <arpa/inet.h>
    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
      printf("inet_pton error\n");
    }

    if (connect(sockfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0) {
      //printf("unuseful port: %d\n", i);
      close(sockfd);
      continue;
    }
    else {
      printf("useful port: %d\n", i);
      close(sockfd);
      continue;
    }
  }

  exit(0);
}

程序实例输出:


运行程序,输入要扫描的IP地址,起始端口号和最终端口号。然后就会列出打开的端口。这里我用127.0.0.1测试自己的电脑打开的可被连接的TCP端口。

程序解释:

程序是单进程的方式。

argc判断输入的命令是否正确。

atoi()将char *格式的字符串转换为int格式

整个过程都是正常的创建TCP socket和connect的过程,比较简单。

sockfd = socket()需要在for循环里面,因为TCP的套接字描述符不能重用,需要在每个TCP的connect创建连接之前重新创建一个新的套接字描述符。

每次connect之后都需要利用close()把套接字描述符关闭,从而释放系统资源,避免超过可创建描述符达到上限而无法创建新的套接字(关于上限的问题还需要进一步查资料)。关于套接字可以参考 http://hi.baidu.com/hwzaeolskllprze/item/efd6a7c617168750bcef69f7 加深理解。



本文链接http://element-ui.cn/news/show-576707.aspx