Winsock:连接套接字问题
Winsock: connecting socket issue
我认为 connect() 函数对我来说工作不正常。我不知道问题是出在 "ip/port" 作业中还是在
hostinfo.sin_addr.s_addr = inet_addr(x)- 值。有人可以给我一个线索吗?顺便说一句,我是编程新手。
编译器让我回答 "HOST IP" 然后 "START PORT",但在我键入 "STOP PORT" 之前循环开始。
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment(lib, "Ws2_32.lib")
#include <string>
#include <WinSock2.h>
#include <Windows.h>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#define SCK_VERSION2 0x0202
#define WIN32_LEAN_AND_MEAN
using namespace std;
int main()
{
dos_console();
WSADATA wsadata;
SOCKET sock;
SOCKADDR_IN hostinfo;
char ip[20];
int start;
int stop;
int search;
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
{
printf("ERROR: ");
};
printf("HOST IP: ");
gets_s(ip);
printf("START PORT: ");
scanf_s("%s", &start);
printf("STOP PORT: ");
scanf_s("%s", &stop);
hostinfo.sin_family = AF_INET;
hostinfo.sin_addr.s_addr = inet_addr(ip);
for (search = start; search <= stop; search++)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
printf("ERROR: ");
}
hostinfo.sin_port = htons(search);
if (connect(sock, (SOCKADDR*)(&hostinfo), sizeof(hostinfo)) == SOCKET_ERROR)
{
printf("ERROR: ");
}
else
{
printf("PORT: ", search, " - OPEN");
closesocket(sock);
WSACleanup();
}
printf("PORTSCANNER: DONE");
}
system("PAUSE");
return 0;
};
正如 jungy 在评论中所述,您的 start
和 stop
变量是整数,但您使用 %s
从 scanf_s()
读取它们,而您应该使用 %d
代替。您没有检查 gets_s()
或 scanf_s()
的 return 值是否存在解析错误。
您还需要将 WSACleanup()
移出循环,否则如果 connect()
失败一次,则后续对 socket()
的调用将失败并出现 WSANOTINITIALISED
错误。
当 connect()
成功时,您也会泄漏每个套接字。
尝试更像这样的东西:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <string>
#include <WinSock2.h>
#include <Windows.h>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#define SCK_VERSION2 0x0202
using namespace std;
int main()
{
dos_console();
WSADATA wsadata = {0};
SOCKET sock;
SOCKADDR_IN hostinfo = {0};
char ip[256] = {0};
unsigned short start;
unsigned short stop;
unsigned short search;
int ret;
hostinfo.sin_family = AF_INET;
ret = WSAStartup(MAKEWORD(2, 2), &wsadata);
if (ret != 0)
{
printf("ERROR: WSAStartup() error %d\n", ret);
goto done;
}
printf("HOST IP: ");
if (!gets_s(ip))
{
printf("ERROR: HOST IP\n");
goto cleanup;
}
hostinfo.sin_addr.s_addr = inet_addr(ip);
if (hostinfo.sin_addr.s_addr == INADDR_NONE)
{
printf("ERROR: HOST IP\n");
goto cleanup;
}
printf("START PORT: ");
if (scanf_s("%hu", &start) != 1)
{
printf("ERROR: START PORT\n");
goto cleanup;
}
printf("STOP PORT: ");
if (scanf_s("%hu", &stop) != 1)
{
printf("ERROR: STOP PORT\n");
goto cleanup;
}
if ((start == 0) || (stop == 0) || (stop < start))
{
printf("ERROR: PORT RANGE\n");
goto cleanup;
}
for (search = start; search <= stop; search++)
{
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
printf("ERROR: socket() error %d\n", WSAGetLastError());
goto cleanup;
}
hostinfo.sin_port = htons(search);
if (connect(sock, (SOCKADDR*) &hostinfo, sizeof(hostinfo)) == SOCKET_ERROR)
{
printf("PORT: %hu - NOT OPEN\n", search);
}
else
{
printf("PORT: %hu - OPEN\n", search);
}
closesocket(sock);
}
printf("PORTSCANNER: DONE\n");
cleanup:
WSACleanup();
done:
system("PAUSE");
return 0;
}
因为您无论如何都在使用 C++(从 using namespace std
语句可以看出),我会建议更像这样的东西:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
#pragma comment(lib, "Ws2_32.lib")
#define SCK_VERSION2 MAKEWORD(2, 2)
using namespace std;
struct sWSA
{
WSADATA wsadata;
sWSA()
{
ZeroMemory(&wsadata, sizeof(wsadata));
int ret = WSAStartup(SCK_VERSION2, &wsadata);
if (ret != 0)
{
ostringstream oss;
oss << "WSAStartup() error " << ret;
throw runtime_error(oss.str());
}
}
~sWSA()
{
WSACleanup();
}
};
struct sSocket
{
SOCKET sock;
sSocket()
{
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
ostringstream oss;
oss << "socket() error " << WSAGetLastError();
throw runtime_error(oss.str());
}
}
~sSocket()
{
closesocket(sock);
}
bool connect(SOCKADDR_IN &host)
{
return (connect(sock, reinterpret_cast<SOCKADDR*>(&host), sizeof(host)) == 0);
}
};
int main()
{
dos_console();
SOCKADDR_IN hostinfo = {0};
string ip;
unsigned short start;
unsigned short stop;
unsigned short search;
hostinfo.sin_family = AF_INET;
try
{
sWSA wsa;
cout << "HOST IP: ";
if (!getline(cin, ip))
throw runtime_error("HOST IP");
hostinfo.sin_addr.s_addr = inet_addr(ip.c_str());
if (hostinfo.sin_addr.s_addr == INADDR_NONE)
throw runtime_error("HOST IP");
cout << "START PORT: ";
if (!(cin >> start))
throw runtime_error("START PORT");
cout << "STOP PORT: ";
if (!(cin >> stop))
throw runtime_error("STOP PORT");
if ((start == 0) || (stop == 0) || (stop < start))
throw runtime_error("PORT RANGE");
for (search = start; search <= stop; search++)
{
hostinfo.sin_port = htons(search);
sSocket s;
cout << "PORT: " << search << " - " << s.connect(hostinfo) ? "OPEN" : "NOT OPEN" << endl;
}
cout << "PORTSCANNER: DONE" << endl;
}
catch (const std::exception &e)
{
cout << "ERROR: " << e.what() << endl;
}
system("PAUSE");
return 0;
}
现在我已经 decleraed、开始、停止、搜索为 unsigned short 并将它们读取为 (%hu),我还将 WSACleanup 移出循环并检查错误。它似乎工作但在我尝试使用 connect()
时给我一个错误
if (connect(sock, (SOCKADDR*)(&hostinfo), sizeof(hostinfo))== SOCKET_ERROR)
{
printf("PORT: %hu - STÄNGD\n", search);
}
else
{
printf("PORT: %hu - ÖPPEN\n", search);
}
closesocket(sock);
Remy Lebeau:我试图在我的编译器中复制并粘贴您的代码,我给了我一些错误,我根据我的编译器进行了更正,但它仍然在 connect() 中给我同样的错误。
我在防火墙 (5000-5010) 中打开了一些端口,但仍然出现此错误,我在一些较旧的线程中读到我必须将套接字配置为非阻塞套接字。这可能是问题所在吗?
现在这是我的代码:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment(lib, "Ws2_32.lib")
#include <stdio.h>
#include <iostream>
#include <string>
#include <WinSock2.h>
#include <Windows.h>
#include <cstring>
#include <fstream>
#include <cstdlib>
#include <iodos.h>
#include <sdkddkver.h>
#include <conio.h>
#define SCK_VERSION2 0x0202
#define WIN32_LEAN_AND_MEAN
using namespace std;
int main()
{
dos_console();
WSADATA wsadata;
SOCKET sock;
SOCKADDR_IN hostinfo;
char ip[20];
unsigned short start;
unsigned short stop;
unsigned short search;
int err;
hostinfo.sin_family = AF_INET;
err = WSAStartup(MAKEWORD(2, 2), &wsadata);
if (err != 0)
{
printf("ERROR: Wsadata error");
};
printf("HOST IP: ");
if (!gets_s(ip))
{
printf("ERROR: HOST IP error");
goto cleanup;
}
hostinfo.sin_addr.s_addr = inet_addr(ip);
if (hostinfo.sin_addr.s_addr == INADDR_NONE)
{
printf("ERROR: HOST IP 2 error");
goto cleanup;
}
printf("START PORT: ");
if (scanf_s("%hu", &start) != 1)
{
printf("ERROR: START PORT");
goto cleanup;
}
printf("STOP PORT: ");
if (scanf_s("%hu", &stop) != 1)
{
printf("ERROR: STOP PORT");
goto cleanup;
}
for (search = start; search <= stop; search++)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
printf("ERROR: socket error"), WSAGetLastError();
}
hostinfo.sin_port = htons(search);
if (connect(sock, (SOCKADDR*)(&hostinfo), sizeof(hostinfo))== SOCKET_ERROR)
{
printf("PORT: %hu - STÄNGD\n", search);
}
else
{
printf("PORT: %hu - ÖPPEN\n", search);
}
closesocket(sock);
}
printf("PORTSCANNER DONE");
cleanup:
WSACleanup();
done:
system("PAUSE");
return 0;
};
我认为 connect() 函数对我来说工作不正常。我不知道问题是出在 "ip/port" 作业中还是在 hostinfo.sin_addr.s_addr = inet_addr(x)- 值。有人可以给我一个线索吗?顺便说一句,我是编程新手。
编译器让我回答 "HOST IP" 然后 "START PORT",但在我键入 "STOP PORT" 之前循环开始。
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment(lib, "Ws2_32.lib")
#include <string>
#include <WinSock2.h>
#include <Windows.h>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#define SCK_VERSION2 0x0202
#define WIN32_LEAN_AND_MEAN
using namespace std;
int main()
{
dos_console();
WSADATA wsadata;
SOCKET sock;
SOCKADDR_IN hostinfo;
char ip[20];
int start;
int stop;
int search;
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
{
printf("ERROR: ");
};
printf("HOST IP: ");
gets_s(ip);
printf("START PORT: ");
scanf_s("%s", &start);
printf("STOP PORT: ");
scanf_s("%s", &stop);
hostinfo.sin_family = AF_INET;
hostinfo.sin_addr.s_addr = inet_addr(ip);
for (search = start; search <= stop; search++)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
printf("ERROR: ");
}
hostinfo.sin_port = htons(search);
if (connect(sock, (SOCKADDR*)(&hostinfo), sizeof(hostinfo)) == SOCKET_ERROR)
{
printf("ERROR: ");
}
else
{
printf("PORT: ", search, " - OPEN");
closesocket(sock);
WSACleanup();
}
printf("PORTSCANNER: DONE");
}
system("PAUSE");
return 0;
};
正如 jungy 在评论中所述,您的 start
和 stop
变量是整数,但您使用 %s
从 scanf_s()
读取它们,而您应该使用 %d
代替。您没有检查 gets_s()
或 scanf_s()
的 return 值是否存在解析错误。
您还需要将 WSACleanup()
移出循环,否则如果 connect()
失败一次,则后续对 socket()
的调用将失败并出现 WSANOTINITIALISED
错误。
当 connect()
成功时,您也会泄漏每个套接字。
尝试更像这样的东西:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <string>
#include <WinSock2.h>
#include <Windows.h>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
#define SCK_VERSION2 0x0202
using namespace std;
int main()
{
dos_console();
WSADATA wsadata = {0};
SOCKET sock;
SOCKADDR_IN hostinfo = {0};
char ip[256] = {0};
unsigned short start;
unsigned short stop;
unsigned short search;
int ret;
hostinfo.sin_family = AF_INET;
ret = WSAStartup(MAKEWORD(2, 2), &wsadata);
if (ret != 0)
{
printf("ERROR: WSAStartup() error %d\n", ret);
goto done;
}
printf("HOST IP: ");
if (!gets_s(ip))
{
printf("ERROR: HOST IP\n");
goto cleanup;
}
hostinfo.sin_addr.s_addr = inet_addr(ip);
if (hostinfo.sin_addr.s_addr == INADDR_NONE)
{
printf("ERROR: HOST IP\n");
goto cleanup;
}
printf("START PORT: ");
if (scanf_s("%hu", &start) != 1)
{
printf("ERROR: START PORT\n");
goto cleanup;
}
printf("STOP PORT: ");
if (scanf_s("%hu", &stop) != 1)
{
printf("ERROR: STOP PORT\n");
goto cleanup;
}
if ((start == 0) || (stop == 0) || (stop < start))
{
printf("ERROR: PORT RANGE\n");
goto cleanup;
}
for (search = start; search <= stop; search++)
{
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
printf("ERROR: socket() error %d\n", WSAGetLastError());
goto cleanup;
}
hostinfo.sin_port = htons(search);
if (connect(sock, (SOCKADDR*) &hostinfo, sizeof(hostinfo)) == SOCKET_ERROR)
{
printf("PORT: %hu - NOT OPEN\n", search);
}
else
{
printf("PORT: %hu - OPEN\n", search);
}
closesocket(sock);
}
printf("PORTSCANNER: DONE\n");
cleanup:
WSACleanup();
done:
system("PAUSE");
return 0;
}
因为您无论如何都在使用 C++(从 using namespace std
语句可以看出),我会建议更像这样的东西:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
#pragma comment(lib, "Ws2_32.lib")
#define SCK_VERSION2 MAKEWORD(2, 2)
using namespace std;
struct sWSA
{
WSADATA wsadata;
sWSA()
{
ZeroMemory(&wsadata, sizeof(wsadata));
int ret = WSAStartup(SCK_VERSION2, &wsadata);
if (ret != 0)
{
ostringstream oss;
oss << "WSAStartup() error " << ret;
throw runtime_error(oss.str());
}
}
~sWSA()
{
WSACleanup();
}
};
struct sSocket
{
SOCKET sock;
sSocket()
{
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
{
ostringstream oss;
oss << "socket() error " << WSAGetLastError();
throw runtime_error(oss.str());
}
}
~sSocket()
{
closesocket(sock);
}
bool connect(SOCKADDR_IN &host)
{
return (connect(sock, reinterpret_cast<SOCKADDR*>(&host), sizeof(host)) == 0);
}
};
int main()
{
dos_console();
SOCKADDR_IN hostinfo = {0};
string ip;
unsigned short start;
unsigned short stop;
unsigned short search;
hostinfo.sin_family = AF_INET;
try
{
sWSA wsa;
cout << "HOST IP: ";
if (!getline(cin, ip))
throw runtime_error("HOST IP");
hostinfo.sin_addr.s_addr = inet_addr(ip.c_str());
if (hostinfo.sin_addr.s_addr == INADDR_NONE)
throw runtime_error("HOST IP");
cout << "START PORT: ";
if (!(cin >> start))
throw runtime_error("START PORT");
cout << "STOP PORT: ";
if (!(cin >> stop))
throw runtime_error("STOP PORT");
if ((start == 0) || (stop == 0) || (stop < start))
throw runtime_error("PORT RANGE");
for (search = start; search <= stop; search++)
{
hostinfo.sin_port = htons(search);
sSocket s;
cout << "PORT: " << search << " - " << s.connect(hostinfo) ? "OPEN" : "NOT OPEN" << endl;
}
cout << "PORTSCANNER: DONE" << endl;
}
catch (const std::exception &e)
{
cout << "ERROR: " << e.what() << endl;
}
system("PAUSE");
return 0;
}
现在我已经 decleraed、开始、停止、搜索为 unsigned short 并将它们读取为 (%hu),我还将 WSACleanup 移出循环并检查错误。它似乎工作但在我尝试使用 connect()
时给我一个错误 if (connect(sock, (SOCKADDR*)(&hostinfo), sizeof(hostinfo))== SOCKET_ERROR)
{
printf("PORT: %hu - STÄNGD\n", search);
}
else
{
printf("PORT: %hu - ÖPPEN\n", search);
}
closesocket(sock);
Remy Lebeau:我试图在我的编译器中复制并粘贴您的代码,我给了我一些错误,我根据我的编译器进行了更正,但它仍然在 connect() 中给我同样的错误。
我在防火墙 (5000-5010) 中打开了一些端口,但仍然出现此错误,我在一些较旧的线程中读到我必须将套接字配置为非阻塞套接字。这可能是问题所在吗?
现在这是我的代码:
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment(lib, "Ws2_32.lib")
#include <stdio.h>
#include <iostream>
#include <string>
#include <WinSock2.h>
#include <Windows.h>
#include <cstring>
#include <fstream>
#include <cstdlib>
#include <iodos.h>
#include <sdkddkver.h>
#include <conio.h>
#define SCK_VERSION2 0x0202
#define WIN32_LEAN_AND_MEAN
using namespace std;
int main()
{
dos_console();
WSADATA wsadata;
SOCKET sock;
SOCKADDR_IN hostinfo;
char ip[20];
unsigned short start;
unsigned short stop;
unsigned short search;
int err;
hostinfo.sin_family = AF_INET;
err = WSAStartup(MAKEWORD(2, 2), &wsadata);
if (err != 0)
{
printf("ERROR: Wsadata error");
};
printf("HOST IP: ");
if (!gets_s(ip))
{
printf("ERROR: HOST IP error");
goto cleanup;
}
hostinfo.sin_addr.s_addr = inet_addr(ip);
if (hostinfo.sin_addr.s_addr == INADDR_NONE)
{
printf("ERROR: HOST IP 2 error");
goto cleanup;
}
printf("START PORT: ");
if (scanf_s("%hu", &start) != 1)
{
printf("ERROR: START PORT");
goto cleanup;
}
printf("STOP PORT: ");
if (scanf_s("%hu", &stop) != 1)
{
printf("ERROR: STOP PORT");
goto cleanup;
}
for (search = start; search <= stop; search++)
{
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
{
printf("ERROR: socket error"), WSAGetLastError();
}
hostinfo.sin_port = htons(search);
if (connect(sock, (SOCKADDR*)(&hostinfo), sizeof(hostinfo))== SOCKET_ERROR)
{
printf("PORT: %hu - STÄNGD\n", search);
}
else
{
printf("PORT: %hu - ÖPPEN\n", search);
}
closesocket(sock);
}
printf("PORTSCANNER DONE");
cleanup:
WSACleanup();
done:
system("PAUSE");
return 0;
};