C++ 最佳及;快速查找ip地址是否可访问的方法
我需要最快的方法来查看是否可以访问ip地址。在每个ip地址上都有一个服务器在侦听特定端口,因此如果您的方法即将查找服务器是否在侦听端口,请告诉我 原因是,假设我有10个ip地址,其中10个服务器在每个ip地址的端口101上侦听。我希望我的客户能够找到一个可访问的ip地址,并尽可能快地连接到该地址(我不希望他等待30秒以确定ip地址是否可访问,然后尝试列表中的下一个ip地址)C++ 最佳及;快速查找ip地址是否可访问的方法,c++,windows,ip-address,C++,Windows,Ip Address,我需要最快的方法来查看是否可以访问ip地址。在每个ip地址上都有一个服务器在侦听特定端口,因此如果您的方法即将查找服务器是否在侦听端口,请告诉我 原因是,假设我有10个ip地址,其中10个服务器在每个ip地址的端口101上侦听。我希望我的客户能够找到一个可访问的ip地址,并尽可能快地连接到该地址(我不希望他等待30秒以确定ip地址是否可访问,然后尝试列表中的下一个ip地址) 可能必须同时在踏板上进行 尝试从中使用connect()函数打开套接字。它尽可能快,如果端口未打开,它将不会响应SYN数据
可能必须同时在踏板上进行 尝试从中使用connect()函数打开套接字。它尽可能快,如果端口未打开,它将不会响应SYN数据包 正如您所意识到的,关键问题是占用一个线程,该线程必须等待SYN-ACK才能执行任何其他操作幸运的是,您不需要线程来;然而,编程异步操作可能很微妙;因此,我建议在并行调度TCP/IP连接操作时使用。。。由于内核正在执行繁重的任务,因此只需一个线程就可以完成。根据您的网络硬件,您可以使用libevent每秒进行100次或数千次连接
另一个选择是哪个更复杂。但是,既然你正在使用C++,你可能会更好。
尝试使用一个连接函数打开一个套接字。它尽可能快,如果端口未打开,它将不会响应SYN数据包
正如您所意识到的,关键问题是占用一个线程,该线程必须等待SYN-ACK才能执行任何其他操作幸运的是,您不需要线程来;然而,编程异步操作可能很微妙;因此,我建议在并行调度TCP/IP连接操作时使用。。。由于内核正在执行繁重的任务,因此只需一个线程就可以完成。根据您的网络硬件,您可以使用libevent每秒进行100次或数千次连接另一个选择是哪个更复杂。但是由于你使用C++可能会更好地适应你的情况。
通常随机尝试连接一个短的时间就足够了。 可达性不是很重要,从您到服务器的路由存在这一事实并不重要,您是否可以连接到所述服务器才重要。通常,您自己的代码运行速度与您可以设计的任何其他可达性方法一样快
如果你有太长时间的问题,那么试着调整你的回答的长度,或者有更紧的超时时间 简单算法:shuffle IP addresses
foreach IP in addresses
attempt connect
if succeed then
break
通常,在短时间内随机尝试连接就足够了 可达性不是很重要,从您到服务器的路由存在这一事实并不重要,您是否可以连接到所述服务器才重要。通常,您自己的代码运行速度与您可以设计的任何其他可达性方法一样快 如果你有太长时间的问题,那么试着调整你的回答的长度,或者有更紧的超时时间 简单算法:
shuffle IP addresses
foreach IP in addresses
attempt connect
if succeed then
break
虽然您可以快速确定IP是可访问的,但您的问题是确定IP是不可访问的。原因是您不能总是确定IP不可访问。虽然在某些情况下,您会收到IP不可访问的肯定通知,但通常您的代码不会听到答案,等待一段时间后,您的代码将假定IP不可访问 决定超时的问题是网络拓扑。如果您有一个大的拓扑结构(如Internet),那么如果您试图连接到一个“很远”的IP,您将需要一个大的超时来处理潜在的高延迟
根据您的描述,最好是尝试同时连接到所有服务器,并使用第一个接受连接的服务器。您可以使用线程,也可以使用非阻塞套接字。在非阻塞连接中,连接调用会立即返回,然后您可以使用来有效地确定连接调用何时完成(成功或出现错误)。虽然您可以快速确定某个IP是可访问的,但您的问题是确定某个IP是不可访问的。原因是您不能总是确定IP不可访问。虽然在某些情况下,您会收到IP不可访问的肯定通知,但通常您的代码不会听到答案,等待一段时间后,您的代码将假定IP不可访问 决定超时的问题是网络拓扑。如果您有一个大的拓扑结构(如Internet),那么如果您试图连接到一个“很远”的IP,您将需要一个大的超时来处理潜在的高延迟
根据您的描述,最好是尝试同时连接到所有服务器,并使用第一个接受连接的服务器。您可以使用线程,也可以使用非阻塞套接字。在非阻塞连接中,连接调用会立即返回,然后您可以使用来有效地确定连接调用何时完成(成功或出现错误)。下面是可用于同时创建传出连接的代码 在IP上迭代,并在循环中生成传出的连接。
每个连接
conn\u t*
都作为LParam发布在窗口消息中-同时发布
您应该监视消息并仅将第一个连接保存在某个位置-忽略(删除)其他连接
#define MSG_NEW_CONNECTION (WM_USER + 1)
struct conn_t {
SOCKET s;
sockaddr_in server;
};
static
UINT OutgoingWorker(LPVOID param)
{
// `param` holds "conn_t*"
assert(param);
if (!param) return 0;
conn_t* c = (conn_t*)param;
if (SOCKET_ERROR == connect(c->s, (SOCKADDR*)&c->server, sizeof c->server)) {
closesocket(c->s);
return 0;
}
PostMessage(mainwnd, MSG_NEW_CONNECTION, 0, (LPARAM)c); // <-- mainwnd handle
return 0;
}
conn_t*
SpawnOutgoing(const char* dest_ip, const USHORT dest_port)
{
if (!dest_ip) return NULL;
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == s) {
return NULL;
}
conn_t* c = new conn_t;
// Create the socket here but connect it in the worker
memset(&c->server, 0, sizeof sockaddr_in);
c->server.sin_family = AF_INET;
c->server.sin_addr.s_addr = inet_addr(dest_ip);
c->server.sin_port = htons(dest_port);
c->s = s;
CreateThread(0, 0, OutgoingWorker, c);
return c;
}
#定义消息新连接(WM_用户+1)
结构连接{
插座;
服务器中的sockaddr_;
};