还是多线程ping的问题还没解决。

fffanpei 2009-11-18 10:26:44
void CPing::Ping(UINT nRetries,LPCSTR pstrHost,HWND hWnd)
{
SOCKET rawSocket;
LPHOSTENT lpHost;
UINT nLoop;
int nRet;
struct sockaddr_in saDest;
struct sockaddr_in saSrc;
DWORD dwTimeSent;
DWORD dwElapsed;
u_char cTTL;

m_hWnd = hWnd;

CString str;

ASSERT(IsWindow(hWnd));
// Create a Raw socket
rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (rawSocket == SOCKET_ERROR)
{
WSAError("socket()");
return;
}

// Lookup host
lpHost = gethostbyname(pstrHost);
if (lpHost == NULL)
{
str.Format("Host not found: %s", pstrHost);
::PostMessage(m_hWnd,WM_MSG_STATUS, 0, (LPARAM) AllocBuffer(str));
::PostMessage(m_hWnd,WM_PING_END, 0, 0);
return;
}

// Setup destination socket address
saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
saDest.sin_family = AF_INET;
saDest.sin_port = 0;

// Tell the user what we're doing
str.Format("Pinging %s [%s] with %d bytes of data:",
pstrHost,
inet_ntoa(saDest.sin_addr),
REQ_DATASIZE);
::PostMessage(m_hWnd,WM_MSG_STATUS, 1, (LPARAM) AllocBuffer(str));

// Ping multiple times
for (nLoop = 0; nLoop < nRetries; nLoop++)
{
// Send ICMP echo request
TRACE("ping %s \n",pstrHost);
SendEchoRequest(rawSocket, &saDest);

nRet = WaitForEchoReply(rawSocket);
if (nRet == SOCKET_ERROR)
{
WSAError("select()");
break;
}
if (!nRet)
{
str.Format("Request Timed Out");
::PostMessage(m_hWnd,WM_MSG_STATUS, 3, (LPARAM) AllocBuffer(str));
}
else

{

// Receive reply
dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL);

// Calculate elapsed time
dwElapsed = GetTickCount() - dwTimeSent;
str.Format("Reply[%d] from: %s: bytes=%d time=%ldms TTL=%d",
nLoop+1,
inet_ntoa(saSrc.sin_addr),
REQ_DATASIZE,
dwElapsed,
cTTL);

::PostMessage(m_hWnd,WM_MSG_STATUS, 2, (LPARAM) AllocBuffer(str));

Sleep(1);
}
}

::PostMessage(m_hWnd,WM_PING_END, 0, 1);

nRet = closesocket(rawSocket);
if (nRet == SOCKET_ERROR)
WSAError("closesocket()");

}


int CPing::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr)
{
static ECHOREQUEST echoReq;
static nId = 1;
static nSeq = 1;
int nRet;

// Fill in echo request
echoReq.icmpHdr.Type = ICMP_ECHOREQ;
echoReq.icmpHdr.Code = 0;
echoReq.icmpHdr.Checksum = 0;
echoReq.icmpHdr.ID = nId++;
echoReq.icmpHdr.Seq = nSeq++;

// Fill in some data to send
for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
echoReq.cData[nRet] = ' '+nRet;

// Save tick count when sent
echoReq.dwTime = GetTickCount();

// Put data in packet and compute checksum
echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST));

// Send the echo request
nRet = sendto(s, /* socket */
(LPSTR)&echoReq, /* buffer */
sizeof(ECHOREQUEST),
0, /* flags */
(LPSOCKADDR)lpstToAddr, /* destination */
sizeof(SOCKADDR_IN)); /* address length */

if (nRet == SOCKET_ERROR)
WSAError("sendto()");
return (nRet);
}


DWORD CPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL)
{
ECHOREPLY echoReply;
int nRet;
int nAddrLen = sizeof(struct sockaddr_in);

// Receive the echo reply
nRet = recvfrom(s, // socket
(LPSTR)&echoReply, // buffer
sizeof(ECHOREPLY), // size of buffer
0, // flags
(LPSOCKADDR)lpsaFrom, // From address
&nAddrLen); // pointer to address len

// Check return value
if (nRet == SOCKET_ERROR)
WSAError("recvfrom()");

// return time sent and IP TTL
*pTTL = echoReply.ipHdr.TTL;

return(echoReply.echoRequest.dwTime);
}


int CPing::WaitForEchoReply(SOCKET s)
{
struct timeval Timeout;
fd_set readfds;

readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;

return(select(1, &readfds, NULL, NULL, &Timeout));
}

void CPing::WSAError(LPCSTR lpMsg)
{
CString strMsg;
strMsg.Format("%s - WSAError: %ld",lpMsg,WSAGetLastError());
::PostMessage(m_hWnd,WM_MSG_STATUS, 0, (LPARAM) AllocBuffer(strMsg));
}





u_short CPing::in_cksum(u_short *addr, int len)
{
register int nleft = len;
register u_short *w = addr;
register u_short answer;
register int sum = 0;

/*
* Our algorithm is simple, using a 32 bit accumulator (sum),
* we add sequential 16 bit words to it, and at the end, fold
* back all the carry bits from the top 16 bits into the lower
* 16 bits.
*/
while( nleft > 1 ) {
sum += *w++;
nleft -= 2;
}

/* mop up an odd byte, if necessary */
if( nleft == 1 ) {
u_short u = 0;

*(u_char *)(&u) = *(u_char *)w ;
sum += u;
}

/*
* add back carry outs from top 16 bits to low 16 bits
*/
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}

这个例子是从网站上下的,自己建立了一个CWinThread的线程。
里面包括CPing的对象。
现在有个问题,void CPing::Ping(UINT nRetries,LPCSTR pstrHost,HWND hWnd)
函数里面多线程可能同时发包,比如20个ip地址,有的ip目前不同,
可能WaitForEchoReply收到回应时间比较长。
比如192.168.2.10和192.168.2.20,如果192.168.2.10不通,192.168.2.20通。
同时ping的时候,192.168.2.10的线程可能会收到192.168.2.20返回的消息,认为是连接的。
如果判断返回消息的ip啊?程序改如何改啊。
弄了2天了,希望大家帮忙啊。
...全文
178 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2009-11-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 zhao4zhong1 的回复:]
个人认为还不如
system("start ping -n1 192.168.0.1 >1.txt");
system("start ping -n1 192.168.0.2 >2.txt");
system("start ping -n1 192.168.0.3 >3.txt");
然后读1.txt,2.txt,3.txt的内容判断呢
[/Quote]
system("start ping -n 1 192.168.0.1 >1.txt");
system("start ping -n 1 192.168.0.2 >2.txt");
system("start ping -n 1 192.168.0.3 >3.txt");
//...
system("start ping -n 1 192.168.0.100 >100.txt");
Sleep(5000);
然后读1.txt,2.txt,3.txt,...,100.txt的内容判断

因为ping的前面有start,所以不会等上一个ping结束才开始下一个ping,100个和1个费时应该差不多。
其实说白了就是采取多进程的方法代替楼主多线程的方法。参考《UNIX编程艺术》
fffanpei 2009-11-23
  • 打赏
  • 举报
回复
恩 好的
我说的那个问题 出现了吗?
江川 2009-11-23
  • 打赏
  • 举报
回复
你参考一下人家这么编程的,比较容易管理

http://www.codeguru.com/cpp/i-n/network/messaging/article.php/c5453/
fffanpei 2009-11-23
  • 打赏
  • 举报
回复
5516853@qq.com 吧
我再发一遍
yishow 2009-11-23
  • 打赏
  • 举报
回复
多线程ping好像是有问题的,记得我以前也写过,具体原因太久忘记了
江川 2009-11-23
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 fffanpei 的回复:]
引用 12 楼 successqigao 的回复:
引用 11 楼 fffanpei 的回复:
引用 9 楼 zhao4zhong1 的回复:
个人认为还不如
system("start ping -n1 192.168.0.1 >1.txt");
system("start ping -n1 192.168.0.2 >2.txt");
system("start ping -n1 192.168.0.3 >3.txt");
然后读1.txt,2.txt,3.txt的内容判断呢


您说的这个方法,如果ip不通需要花费时间长吧。
如果有100个设备,轮循一遍需要很长时间吧?


一般ping会设置超时,比如1S超时,那么100时间就是100 * 1


您收到了吗?看到现象了吧
[/Quote]

没有收到。
fffanpei 2009-11-23
  • 打赏
  • 举报
回复
问题还没有解决啊,谁能帮看看啊。
帮顶也行。
fffanpei 2009-11-23
  • 打赏
  • 举报
回复
int CPing::WaitForEchoReply(SOCKET s)
{
struct timeval Timeout;
int iReturn;
fd_set readfds;

readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;

iReturn = select(1, &readfds, NULL, NULL, &Timeout);
return(iReturn);
}

select怎么才能判断是本线程发送的包,而不是接受别的ip返回的包?
帮我顶起一下吧,谢谢
我不能发言了
fffanpei 2009-11-23
  • 打赏
  • 举报
回复
谁能给我找个或者写个多线程ping的例子啊
比较着急用
fffanpei 2009-11-20
  • 打赏
  • 举报
回复
有人帮看看吗
我在线程里面创建一个CPing成员,
如果多个线程同时CPing,之间可能会接受到别的ip返回的信息,不知道这个如何改啊?
select的时候可以判断ip地址吗?
fffanpei 2009-11-20
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 successqigao 的回复:]
引用 11 楼 fffanpei 的回复:
引用 9 楼 zhao4zhong1 的回复:
个人认为还不如
system("start ping -n1 192.168.0.1 >1.txt");
system("start ping -n1 192.168.0.2 >2.txt");
system("start ping -n1 192.168.0.3 >3.txt");
然后读1.txt,2.txt,3.txt的内容判断呢


您说的这个方法,如果ip不通需要花费时间长吧。
如果有100个设备,轮循一遍需要很长时间吧?


一般ping会设置超时,比如1S超时,那么100时间就是100 * 1
[/Quote]

您收到了吗?看到现象了吧
江川 2009-11-20
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 fffanpei 的回复:]
引用 9 楼 zhao4zhong1 的回复:
个人认为还不如
system("start ping -n1 192.168.0.1 >1.txt");
system("start ping -n1 192.168.0.2 >2.txt");
system("start ping -n1 192.168.0.3 >3.txt");
然后读1.txt,2.txt,3.txt的内容判断呢


您说的这个方法,如果ip不通需要花费时间长吧。
如果有100个设备,轮循一遍需要很长时间吧?
[/Quote]

一般ping会设置超时,比如1S超时,那么100时间就是100 * 1
fffanpei 2009-11-20
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 zhao4zhong1 的回复:]
个人认为还不如
system("start ping -n1 192.168.0.1 >1.txt");
system("start ping -n1 192.168.0.2 >2.txt");
system("start ping -n1 192.168.0.3 >3.txt");
然后读1.txt,2.txt,3.txt的内容判断呢
[/Quote]

您说的这个方法,如果ip不通需要花费时间长吧。
如果有100个设备,轮循一遍需要很长时间吧?
fffanpei 2009-11-20
  • 打赏
  • 举报
回复
我已经发送了
SendEchoRequest(rawSocket, &saDest);

nRet = WaitForEchoReply(rawSocket);
怎么感觉这个线程之中不匹配啊?

[Quote=引用 8 楼 successqigao 的回复:]
发到我的QQ邮箱我看看
5516853
[/Quote]
赵4老师 2009-11-20
  • 打赏
  • 举报
回复
个人认为还不如
system("start ping -n1 192.168.0.1 >1.txt");
system("start ping -n1 192.168.0.2 >2.txt");
system("start ping -n1 192.168.0.3 >3.txt");
然后读1.txt,2.txt,3.txt的内容判断呢
江川 2009-11-20
  • 打赏
  • 举报
回复
发到我的QQ邮箱我看看
5516853
江川 2009-11-18
  • 打赏
  • 举报
回复
每个服务端会在你的客户端绑定一个socket,是唯一的,可以标识的,你不用担心。
fffanpei 2009-11-18
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 successqigao 的回复:]
你运行ping的时候会指定服务器的ip,这样绑定的SOCKET是不一样的对象,能够区分的啊
[/Quote]
您的意思我不用处理吗?
可是我做的效果是会受影响。
我感觉
int CPing::WaitForEchoReply(SOCKET s)
{
struct timeval Timeout;
fd_set readfds;

readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 1;
Timeout.tv_usec = 0;

return(select(1, &readfds, NULL, NULL, &Timeout));
}
函数是不是需要解析哪个ip返回的信息啊
fffanpei 2009-11-18
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 healer_kx 的回复:]
单线程就OK了,多线程往往是为了UI不阻塞才考虑用的,这样弄几乎不会快。。。
[/Quote]

单线程如果设备不同会等待1秒,如果50个设备都不同会等待50秒吧
江川 2009-11-18
  • 打赏
  • 举报
回复
你运行ping的时候会指定服务器的ip,这样绑定的SOCKET是不一样的对象,能够区分的啊
加载更多回复(2)

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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