请教一个简单的问题:为什么recvfrom会接收到其他进程的数据

tymicf 2017-05-10 10:37:56
在网上找到的用ICMP实现ping功能的示例代码,发现这个程序同时运行多个,ping不同的地址的时侯 recvfrom会接收到其他进程的数据,请问这是为什么?怎样解决这个问题?

DWORD WINAPI CIcmpPingDlg::ScanFunc(LPVOID lpParameter)
{

Icmp_Header *m_SendIcmp;
Icmp_Header *icmp;
IpHeader *m_ip;
BYTE IPField[4];
CString str="";
char IPbuf[100]={0};
HWND hwnd=((Pram*)lpParameter)->hwnd;
strcpy(IPbuf,((Pram*)lpParameter)->buf);
str=IPbuf;
//AfxMessageBox(str);
CString temp="";
int index=0;
int len=str.GetLength();
index=str.ReverseFind('.');
temp=str.Right(len-index-1);
IPField[3]=atoi(temp);
CString strDesAddr=str.Left(index+1);
CString cs=strDesAddr;
//AfxMessageBox(strDesAddr);
//=================================================================
while(IPField[3]<255)
{
temp="";
temp.Format("%d",IPField[3]);
strDesAddr=cs+temp;
//AfxMessageBox(strDesAddr);
SOCKET scan_sock=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if(INVALID_SOCKET == scan_sock)
{
return 0;
}
int Timeout = 1000;
int Result = setsockopt(scan_sock, SOL_SOCKET, SO_RCVTIMEO, (char*) &Timeout, sizeof(Timeout));
if (Result == SOCKET_ERROR)
{
return 0;
}

char *DestIpAddr=strDesAddr.GetBuffer(strDesAddr.GetLength());
char IcmpBuffer[32]={0};
char buf[100]={0};
sockaddr_in DestAddr;

DestAddr.sin_addr.s_addr = inet_addr(DestIpAddr);
DestAddr.sin_port = htons(0);
DestAddr.sin_family = AF_INET;
m_SendIcmp = (Icmp_Header*)IcmpBuffer;
m_SendIcmp->Type = 8;
m_SendIcmp->Code = 0;
m_SendIcmp->ID = (USHORT)GetCurrentProcessId();
m_SendIcmp->Sequence = htons(1);
m_SendIcmp->Checksum = 0;
m_SendIcmp->Checksum = checksum((USHORT*)IcmpBuffer, sizeof(IcmpBuffer));

sprintf(buf,"ping %s ...\n",inet_ntoa(DestAddr.sin_addr));
CString strsend=buf;

Result = sendto(scan_sock, IcmpBuffer, sizeof(IcmpBuffer), 0, (SOCKADDR*) &DestAddr, sizeof(DestAddr));
if (Result == SOCKET_ERROR)
{
return 0;
}
//==========================================================================================
CString strrecv="";
memset(buf,0,100);
char RecvBuffer[1024]={0};
sockaddr_in addr;
int Len = sizeof(addr);
Result = recvfrom(scan_sock, RecvBuffer, 1024, 0, (sockaddr*) &addr, &Len);
if (Result == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAETIMEDOUT)
{
return 0;
}
else
{
sprintf(buf,"Host %s is down.\n", DestIpAddr);
strrecv=buf;
}
}
if (Result < sizeof(Ip_Header) + sizeof(Icmp_Header))
{
sprintf(buf,"data error from %d\n", inet_ntoa(addr.sin_addr));
strrecv=buf;
}
m_ip = (Ip_Header*)RecvBuffer;
if ((m_ip->SourceAddr == DestAddr.sin_addr.s_addr) && (m_ip->Protocol == IPPROTO_ICMP))
{
icmp = (Icmp_Header*)(RecvBuffer + sizeof(Ip_Header));
if (icmp->Type != 0)
{
sprintf(buf,"type error %d ", icmp->Type);
strrecv=buf;
return 0;
}
if (icmp->ID != GetCurrentProcessId())
{
sprintf(buf,"id error %d\n", icmp->ID);
strrecv=buf;
return 0;
}
else if ((icmp->Type == 0) && (icmp->ID == GetCurrentProcessId()))
{
sprintf(buf,"Host %s is up.\n", DestIpAddr);
strrecv=buf;
}
}
str=strsend+" ";
str+=strrecv; //结果
if (closesocket(scan_sock) == SOCKET_ERROR)
{
sprintf(buf,"closesocket failed with error %d\n", WSAGetLastError());
return 0;
}
char *tmp=str.GetBuffer(str.GetLength());
char sendbuf[100]={0};
strcpy(sendbuf,tmp);
::SendMessage(hwnd,UM_ADDLIST,0,(LPARAM )sendbuf);
IPField[3]++;
}
return 1;
}
...全文
633 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaohuh421 2017-05-11
  • 打赏
  • 举报
回复
因为是无连接的, 完全没有必要开多个线程进行ping多个地址. 比如你ping局域网, 256个地址, 你完全可以先向256个地址发送ping包后, 再select接收响应. (非阻塞模式) 这样效率比多线程高, 同时, 也更容易组织逻辑与数据结构.
tymicf 2017-05-10
  • 打赏
  • 举报
回复
@像我这么屌的还有六个 发送的时侯填充的目的地址是一个进程一个,不重复。 端口是没有啊! ICMP 不是不能用端口吗? 我是想实现这样的:写一个myping程序 有10 IP址 然后开10个myping程序 每个程序检测一个IP 通不通! 关键就是 recvfrom 收到的包是乱的
三岁、就很帅 2017-05-10
  • 打赏
  • 举报
回复
需要确定发送的时候填充的是否为同一个IP和端口,接受的时候如果绑定的是同一个IP和端口,那上面的现象时必然的
三岁、就很帅 2017-05-10
  • 打赏
  • 举报
回复
你看看这篇讨论的 http://bbs.csdn.net/topics/390624000
tymicf 2017-05-10
  • 打赏
  • 举报
回复
swwllx 你好! 关键是获得的是别的进程的数据。 比如 进程1 ping的是192.168.0.1 进程2 ping的是192.168.0.2 进程3 ping的是192.168.0.3 然后我发现 进程3的recvfrom可能会接收到进程2的数据
三岁、就很帅 2017-05-10
  • 打赏
  • 举报
回复
recvfrom本身有个参数可以获得发包方的地址
tymicf 2017-05-10
  • 打赏
  • 举报
回复
引用 6 楼 cutmelon 的回复:
ICMP是无连接的协议啊,在一个机器上多个进程绑定相同IP地址,相同端口的socket,只有最后一个创建的socket会接收到数据,其它的都是默默地等待,永远也收不到数据。从这点来说,你就不能用多进程来处理。比方说10个地址,可以循环发10个ping包或者用多线程发,单开一个接收线程,统计单位时间内接收到哪些地址的回应
你说的 “在一个机器上多个进程绑定相同IP地址,相同端口的socket” 意思是不是如果我各进程绑定不同的端口 是不是可以实用多进程处理?
tymicf 2017-05-10
  • 打赏
  • 举报
回复
@cutmelon 明白了十分感谢!
cutmelon 2017-05-10
  • 打赏
  • 举报
回复
ICMP是无连接的协议啊,在一个机器上多个进程绑定相同IP地址,相同端口的socket,只有最后一个创建的socket会接收到数据,其它的都是默默地等待,永远也收不到数据。从这点来说,你就不能用多进程来处理。比方说10个地址,可以循环发10个ping包或者用多线程发,单开一个接收线程,统计单位时间内接收到哪些地址的回应

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧