Я написал сканер портов на C ++, который будет работать в Windows, используя Winsock, все работает так, как я хотел, просто очень и очень медленно, он занимает около 10 минут, чтобы сканировать три порта, мне просто интересно, есть ли способ увеличить его производительность!
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <winsock.h>
#include <stdlib.h>
#pragma comment(lib,"WSOCK32.LIB")
int main()
{
WSADATA data;
SOCKET sock;
int err, i, startport, endport;
char ip[20];
struct sockaddr_in sock_addr;
FILE*fp1;
printf("ip: ");
scanf("\n%s", ip);
printf("start port: ");
scanf("%d", &startport);
printf("end port: ");
scanf("%d", &endport);
if ((WSAStartup(MAKEWORD(2, 0), &data) != 0))
{
printf("Error: Winsock did not init!!!\n\n");
}
else
{
for (i = startport; i < endport; i++)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
sock_addr.sin_family = PF_INET;
sock_addr.sin_port = htons(i);
sock_addr.sin_addr.s_addr = inet_addr(ip);
printf("Checking port %d\n", i);
err = connect(sock, (struct sockaddr*)&sock_addr, sizeof(struct sockaddr));
if (err == 0)
{
printf("Port Open!!!\n\n\a");
fp1 = fopen("ports.txt", "a+");
fprintf(fp1, "Port is open: %d\n\n", i);
closesocket(sock);
fclose(fp1);
}
else
{
printf("Port Closed!!!\n\n");
}
}
WSACleanup();
system("ports.txt");
}
}
По умолчанию сокет работает в блокирование Режим. Вы используете один цикл для последовательного соединения с каждым портом, ожидая завершения одного соединения, прежде чем пытаться выполнить следующее. Так что, конечно, производительность будет медленной.
Для того, что вы хотите достичь, вам нужно выполнить несколько вызовов подключения параллельно. У вас есть 3 варианта для этого:
Для каждого блокирующего сокета, который вы создаете, запустите рабочий поток для connect()
Это. Затем вы можете создать несколько сокетов и запускать их потоки одновременно. использование WaitForMultipleObjects()
(или связанная функция), чтобы обнаружить, когда каждый поток завершается, когда его connect()
операция заканчивается.
Это нормально для небольшого количества сокетов, но не масштабируется для больших чисел.
Для каждого сокета, который вы создаете, используйте ioctlsocket(FIONBIO)
перевести его в неблокирующий режим. Затем вы можете создать несколько сокетов и connect()
их в одно время. использование select()
, WSAAsyncSelect()
, или же WSAEventSelect()
обнаружить, когда каждый connect()
операция заканчивается.
Создайте каждый сокет, используя WSASocket()
с WSA_FLAG_OVERLAPPED
флаг включен. Затем вы можете создать несколько сокетов и ConnectEx()
их одновременно, указав отдельный OVERLAPPED
структура для каждого. использование WaitForMultipleObjects()
+GetOverlappedResult()
, или Порт завершения ввода / вывода, обнаружить, когда каждый ConnectEx()
операция заканчивается.
Других решений пока нет …