请高手指教。
小弟在一程序中开了几百个线程,给每个线程传递一个ip地址。利用ICMP模拟Ping的功能,发现当开启一个线程,只ping一个ip时,结果正确,但是开了多个线程,同时ping多台机器时,运行结果就不正确了。查了很多资料,没搞明白,不知道是不是发送或接收缓冲区的问题,请老大们指教。下面是ping的代码。
BOOL Ping(char* addr) //IP地址
{
SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
// 设置超时
int pingtimeout = 1000;
setsockopt(sRaw,SOL_SOCKET,SO_SNDTIMEO,(char *)&pingtimeout,sizeof(int));
setsockopt(sRaw,SOL_SOCKET,SO_RCVTIMEO,(char *)&pingtimeout,sizeof(int));
// 设置目的地址
SOCKADDR_IN dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(0);
dest.sin_addr.S_un.S_addr = inet_addr(addr);
// 创建ICMP封包
char buff[sizeof(ICMP_HDR) + 32];
ICMP_HDR* pIcmp = (ICMP_HDR*)buff;
// 填写ICMP封包数据
pIcmp->icmp_type = 8;
pIcmp->icmp_code = 0;
pIcmp->icmp_id = (USHORT)::GetCurrentThreadId();
pIcmp->icmp_checksum = 0;
pIcmp->icmp_sequence = 0;
// 填充数据部分,
memset(&buff[sizeof(ICMP_HDR)], 'E', 32);
// 开始发送和接收ICMP封包
char recvBuf[128];
SOCKADDR_IN from;
int nLen = sizeof(from);
int nRet;
pIcmp->icmp_checksum = 0;
pIcmp->icmp_timestamp = ::GetTickCount();
pIcmp->icmp_sequence = nSeq;
pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32);
nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));
if(nRet == SOCKET_ERROR)
{closesocket(sRaw);
return FALSE;
}
nRet = ::recvfrom(sRaw, recvBuf, 128, 0, (sockaddr*)&from, &nLen);
if(nRet == SOCKET_ERROR)
{
closesocket(sRaw);
return FALSE;
}
// 下面开始解析接收到的ICMP封包
int nTick = ::GetTickCount();
// 接收到的数据中包含IP头,IP头大小为20个字节,所以加20得到ICMP头
ICMP_HDR* pRecvIcmp = (ICMP_HDR*)(recvBuf + 20); // (ICMP_HDR*)(recvBuf + sizeof(IPHeader));
if(pRecvIcmp->icmp_type != 0) // 回显
{
return FALSE;
}
if(pRecvIcmp->icmp_id != ::GetCurrentThreadId())
{
return FALSE;
} closesocket(sRaw);
return TRUE;
}
小弟在其他的实践中也发现当使用较多的线程时,用winsock发送,接收数据时就会出现不对的情况,但是单一线程或线程较少时是正确的,一直找不到原因。比如说对一代理服务器80端口,发送一个数据包,在线程较少时,返回的结果时正确的,如果开了很多线程,同时对很多的代理服务器的端口进行同样的任务,返回的结果就不正确了,小弟估计是发送或接收缓冲区的问题,但是不知道是不是,那位高手能指点一下。