原始ICMP WInsock,异步I / O.

时间:2015-05-30 18:03:32

标签: c++ sockets winapi select winsock2

我正在做一个程序,允许我同时ping大量不同的IP(大约50-70)。

由于多种原因,我还需要将每个数据包的发送延迟1 ms,特别是当一次发送的数据太多时,某些丢弃ICMP数据包的路由器不会丢失我的数据包(我的数据包发送时间过多)机器,而不是接收器。)

所以我在一个单独的线程中做了这样的事情:

// Send thread
for (;;) {
   [...]
   for (int i = 0; i < ip_count; i++)
   {
      // Send() calls sendto()
      Send(m_socket, ip_array[i]);
      [...]
      Sleep(1); // Delay by 1 ms
   }
   [...]
   lock_until_new_send_operation();
}

在另一个线程中,线程我想用select()接收数据包,就像那个

// Receive thread
FD_ZERO(&m_fdset_read);
FD_SET(m_socket, &m_fdset_read);
int rds_count = select(0, &m_fdset_read, 0, 0, &tvtimeout);
if (rds_count > 0)
    ProcessReadySocket(); // Calls recv() and stuff
else {
    // Timed out
    m_bSendGrapeDone = true;
}

这种方法的问题在于,由于对select()和sento()的调用都使用相同的非阻塞套接字m_socket,因此对sendto()的调用稍后会阻塞,因为当两者都是select()时,send()会生成块。同时调用(由于一些奇怪的原因......在那里看不到这样的逻辑,因为socket是非阻塞的,但它仍然存在,它的丑陋)。

所以我决定使用一个专门用于发送然后替换行

Send(m_socket, ip_array[i]);

Send(m_sendSock, ip_array[i]); // m_sendSock is dedicated to sending only

我在MSDN上读到,对于原始套接字,每个套接字都接收套接字设置的协议的所有数据包(我的是IPPROTO_ICMP ofc)。在这里我引用:

  

使用套接字的应用程序还有其他限制   输入SOCK_RAW。例如,所有应用程序都在监听特定的   protocol将接收为此协议接收的所有数据包

所以我想即使我的数据包是用m_sendSock发送的,我仍然可以在m_socket上使用select()/ recv()接收它们,结果我不能,select()永远不会返回套接字是可读的。所以我有点卡住,我不能同时使用select()和send()。有什么我做错了吗?

(顺便说一句,我想使用原始套接字,而不是内置的windows icmp函数)

TL; DR如何同时发送()和选择()?因为在发送线程上,只要在接收线程上调用select()就发送send()块,即使我在其上使用了FIONBIO(非阻塞)。如果我使用两个不同的插座,一个用于发送,一个用于接收,我在接收插座上什么都没有收到......

谢谢!

0 个答案:

没有答案