gpt4 book ai didi

c - 加速 Windows C 端口扫描程序

转载 作者:行者123 更新时间:2023-11-30 14:55:37 25 4
gpt4 key购买 nike

所以我在 Windows 上开发了一个 C 端口扫描器,但我注意到在某些 IP 上它运行速度非常慢。这是我的代码:

DWORD WINAPI connectPortW(LPVOID lpParam)
{
HANDLE hStdout;
PMYDATA pDataArray;

WSADATA firstsock;
SOCKET s;
struct sockaddr_in sa;
int err;

char * openPorts = (char *)malloc(sizeof(char)*256);
memset(&openPorts[0], 0, strlen(openPorts));

hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if(hStdout == INVALID_HANDLE_VALUE )
{
return 1;
}

pDataArray = (PMYDATA)lpParam;

strncpy((char *)&sa,"",sizeof sa);
sa.sin_family = AF_INET;

if (WSAStartup(MAKEWORD(2,0),&firstsock) != 0)
{
fprintf(stderr,"WSAStartup() failed");
exit(1);
}

sa.sin_addr.s_addr = inet_addr(pDataArray->ip);

s = socket(AF_INET, SOCK_STREAM, 0); //make net a valid socket handle
if(s < 0)
{
perror("\nSocket creation failed"); // perror function prints an error message to stderr
exit(1);
}

sa.sin_port = htons(pDataArray->port);
err = connect(s, (struct sockaddr *)&sa, sizeof sa);

//connection not accepted
if(err == SOCKET_ERROR)
{
printf("%s %-5d Winsock Error Code : %d\n", pDataArray->ip, pDataArray->port, WSAGetLastError());
strcpy("NULL", openPorts);
fflush(stdout);
}
//connection accepted
else
{
printf("%s %-5d accepted \n", pDataArray->ip, pDataArray->port);
sprintf(openPorts, "%i,", pDataArray->port);
if(shutdown(s, SD_BOTH ) == SOCKET_ERROR )
{
perror("\nshutdown");
exit(1);
}
}
closesocket(s);

fflush(stdout);

strcpy(pDataArray->openPorts, openPorts);

free(openPorts);

return 0;
}

请记住,我已经使用了线程,并且每个线程都为同一 IP 上的不同端口 (0 - 1024) 调用此函数。

那么我怎样才能加快速度呢?我不断看到人们谈论非阻塞,这会加快速度吗?如果是的话,我该如何实现它。谢谢!

编辑:在上述“慢速”IP 之一上从 0 - 1024 扫描需要 614 秒(10 分钟)

编辑2:我开始尝试使用非阻塞...我这样做对吗?

ioctlsocket(s, FIONBIO, &on);
connect(s, (struct sockaddr *)&sa, sizeof sa);
FD_ZERO(&fds);
FD_SET(s, &fds);

err = select(s, &fds, &fds, &fds, &tv);

if (err != SOCKET_ERROR && err != 0)
{
sprintf(openPorts + strlen(openPorts),"%i,", pDataArray->port);
}
closesocket(s);

编辑 3:看来这种新方法给我的结果不准确,但速度要快得多。与在同一 IP 上运行 nmap 的结果相比,我似乎获得了更多的开放端口。

最佳答案

我发现您的线程代码有很多问题:

  • 如果发生故障,则会泄漏内存。

  • 您滥用了strlen()调用memset()时在您的openports上多变的。只需删除 memset()一起使用calloc()LocalAlloc(LMEM_ZEROINIT)相反,在分配 openports 时。或者,只需使用调用堆栈即可,因为变量很小:char openPorts[256] = {0};或者更好的是,甚至不使用本地 openports根本没有变量,只需写入 pDataArray->openPorts当您有可用结果时直接进行。

  • 您不应该使用exit()根本不。使用return相反。

  • 从技术上讲,调用WSAStartup()并不违法。/WSACleanup()多次,因为 WinSock 是引用计数的,但是最好只在程序启动/退出时调用它们一次,而不是每个线程。但是,既然你打电话WSAStartup() ,您必须调用 WSACleanup()以保持 WinSock 引用计数平衡。

  • 您想用 strcpy("NULL", openPorts); 做什么? ?您正在写入只读存储器。我想你的意思是strcpy(openPorts, "NULL");相反。

  • 写信给pDataArray->openPorts如果多个线程共享单个缓冲区,则不是线程安全的(您在 , 字符串中使用 sprintf() 意味着可能是这种情况)。当跨多个线程写入缓冲区时,您需要同步对缓冲区的访问。为此,您可以使用临界区或互斥锁。

话虽如此,您正在使用阻塞套接字,因此 connect()将阻塞线程直到 WinSock 内部超时,这在慢速网络上可能需要一段时间。要加快速度,请使用 ioctrlsocket(FIONBIO) 将套接字切换到非阻塞模式。 ,然后使用select()connect() 实现您自己的超时,例如:

DWORD WINAPI connectPortW(LPVOID lpParam)
{
PMYDATA pDataArray = (PMYDATA) lpParam;

HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdout == INVALID_HANDLE_VALUE)
return 1;

WSADATA wsa;
int err = WSAStartup(MAKEWORD(2,0), &wsa);
if (err != 0)
{
fprintf(stderr, "%s %d WSAStartup() failed, Error Code : %d\n", pDataArray->ip, pDataArray->port, err);
return 1;
}

SOCKET s = socket(AF_INET, SOCK_STREAM, 0); //make net a valid socket handle
if (s == INVALID_SOCKET)
{
fprintf(stderr, "%s %d Socket creation failed, Error Code : %d\n", pDataArray->ip, pDataArray->port, WSAGetLastError());
WSACleanup();
return 1;
}

u_long enabled = 1;
if (ioctlsocket(s, FIONBIO, &enabled) == SOCKET_ERROR)
{
fprintf(stderr, "%s %d Socket non-blocking mode failed, Error Code : %d\n", pDataArray->ip, pDataArray->port, WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

struct sockaddr_in sa = {0};
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr(pDataArray->ip);
sa.sin_port = htons(pDataArray->port);

if (connect(s, (struct sockaddr *)&sa, sizeof sa) == SOCKET_ERROR)
{
err = WSAGetLastError();
if (err != WSAEWOULDBLOCK)
{
fprintf(stderr, "%s %d Socket connect failed, Error Code : %d\n", pDataArray->ip, pDataArray->port, err);
closesocket(s);
WSACleanup();
return 1;
}

fd_set wfd, efd;

FD_ZERO(s, &wfd);
FD_SET(s, &wfd);

FD_ZERO(s, &efd);
FD_SET(s, &efd)'

timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;

err = select(0, NULL, &wfd, &efd, &timeout);
if (err == SOCKET_ERROR)
{
fprintf(stderr, "%s %d Socket select failed, Error Code : %d\n", pDataArray->ip, pDataArray->port, WSAGetLastError());
closesocket(s);
WSACleanup();
return 1;
}

if (err == 0)
{
// connect timeout
closesocket(s);
WSACleanup();
return 0;
}

if (FD_ISSET(s, &efd))
{
err = 0;
getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&err, sizeof err);
closesocket(s);
WSACleanup();

switch (err)
{
case WSAETIMEDOUT: // connect timeout
case WSAECONNREFUSED: // port closed
return 0;
}

fprintf(stderr, "%s %d Socket connect failed, Error Code : %d\n", pDataArray->ip, pDataArray->port, err);
return 1;
}
}

// connected!
printf("%s %d accepted\n", pDataArray->ip, pDataArray->port);

// note, this is not thread-safe! Need to sync access to openPorts...
sprintf(pDataArray->openPorts + strlen(pDataArray->openPorts), "%d,", pDataArray->port);

closesocket(s);
WSACleanup();
return 0;
}

关于c - 加速 Windows C 端口扫描程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45696837/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com