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

时间:2021-07-25 22:45:58

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);
}

程序实例输出:

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

端口全连接扫描程序(Linux, socket):TCP的connect方式运行程序,输入要扫描的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 加深理解。