SOCKET sRaw =WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED); 
.....
nRet=::sendto(sRaw,buf,sizeof(ICMP_HDR)+32,0,(SOCKADDR*)&dest,sizeof(dest));
if(nRet==SOCKET_ERROR)
{
    MessageBox("测速失败","错误",MB_OK);
   return 0;
::GetLastError();
}
nRet=recvfrom(sRaw,recvBuf,512,0,(sockaddr*)&from,&len);
if(nRet==SOCKET_ERROR)
    if(::GetLastError()==WSAETIMEDOUT)
{
miss++;
count++;
continue;
         }
问题是这个 recvfrom一直是接受超时?想不明白怎么回事,大家指教一下,谢谢

解决方案 »

  1.   

    既然用WSA_FLAG_OVERLAPPED标志建立起来 socket,就是使用overlapped,要建立一个线称或者设置一个回调函数来得到“异步i/o”的结果;并且i/o函数要使用WSASendto,WSARecvfrom,你这样写是不对的,并且得到error应该用的是WSAGetLastError;你如果不会使用overlapped i/o,我建议你还是使用 blocking socket mode,采用一次sendto,一次recvfrom,等你这种模式调试成功以后,在改成overlapped i/o不迟
      

  2.   

    看了你说的感觉自己知识差的太远了。
    本来我照一本书上写的是 SOCKET sRaw=::socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);,然后书
    上又用了一个SetTimeout函数来设置超时,但这个函数VC中好像没有,没办法我看了ping的源码,看到里面的是用WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED);来创建套接字,然后好像是用setsockopt来设置超时,于是我就给弄了过来,结果 
    我试了一下用SOCKET sRaw=::socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)然后也可以用setsockopt来设置超时,但是最终还是recvfrom总是接收超时,修改变后的部分代码如下:
        SOCKET sRaw=::socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
    //下面为设置超时
    bread=setsockopt(sRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
    timeout=1000;
        bread=setsockopt(sRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout, sizeof(timeout));
              ....
             //下面为填充封包数据
    char buf[sizeof(ICMP_HDR)+32];
    ICMP_HDR *pIcmp=(ICMP_HDR*)buf;
    pIcmp->icmp_type=8;
    pIcmp->icmp_code=0;
    pIcmp->icmp_id=(USHORT)::GetCurrentProcessId();
    pIcmp->icmp_checksum=0;
    pIcmp->icmp_sequence=0;
    memset(&buf[sizeof(ICMP_HDR)],'e',32);
    pIcmp->icmp_checksum=0;
    pIcmp->icmp_timestamp=::GetTickCount();
    pIcmp->icmp_sequence=nseq++;
             pIcmp->icmp_checksum=checksum((USHORT*)buf,sizeof(ICMP_HDR)+32);
    ....
             //以下为发送与接收数据
              nRet=::sendto(sRaw,buf,sizeof(ICMP_HDR)+32,0,(SOCKADDR*)&dest,sizeof(dest));
    if(nRet==SOCKET_ERROR)
    {
    MessageBox("测速失败","错误",MB_OK);
    ::WSAGetLastError();
    return 0;
    }
    nRet=recvfrom(sRaw,recvBuf,1024,0,(sockaddr*)&from,&len);
             if(nRet==SOCKET_ERROR)
    if(::WSAGetLastError()==WSAETIMEDOUT)
    {
    miss++;
    count++;
    continue;
    }
        最终还是这个 recvfrom问题,如常觉得好解决了就帮下我,如果很麻烦了那就算了,我再慢慢看书吧,这两天的问题麻烦你了,谢谢哈
      

  3.   

    问题也不知道怎么了就解决了,郁闷,再次感谢anjuta_c(天天学习不退步)。