如題,有沒有簡單快速的方法,之前沒做過這方便的,有好的方法給分啦
uj5u.com熱心網友回復:
我是MFC新手,看網上說可以用SHELLEXEC呼叫Ping來做這個,不知道具體怎么實作uj5u.com熱心網友回復:
netstat -n 這樣的?uj5u.com熱心網友回復:
不是,比如我要ping 192.168.1.1,怎么才能知道是ping通了還是沒有ping通,要在mfc里實作
uj5u.com熱心網友回復:
就是實作CMD命令模式下 發送ping 命令 接識訓復的碼uj5u.com熱心網友回復:
int i=0;NetworkTest *networktest = (NetworkTest *)pParam;
networktest->m_pinglist.ResetContent();
// 創建ICMP回顯請求包
// char *ICMPPack;
// ICMPPack=new char[networktest->packet];
while (networktest->m_stop)//networktest->m_index
{
char ICMPPack[1024] = {0} ;
PICMP_HEADER pICMPHeader = (PICMP_HEADER)ICMPPack ;
pICMPHeader->bType = 8 ;
pICMPHeader->bCode = 0 ;
pICMPHeader->nId = (USHORT)::GetCurrentProcessId() ;
pICMPHeader->nCheckSum = 0 ;
pICMPHeader->nTimeStamp = 0 ;
memset ( (&ICMPPack[ICMP_HEADER_SIZE]), 'E',ICMP_HEADER_SIZE + networktest->m_packet) ; // 填充資料部分,內容任意
// 初始化WinSock庫
WORD wVersionRequested = MAKEWORD( 2, 2 );
WSADATA wsaData;
if ( WSAStartup( wVersionRequested, &wsaData ) != 0 )
return FALSE ;
// 創建原始套接字
SOCKET RawSock = socket ( AF_INET, SOCK_RAW, IPPROTO_ICMP ) ;
if ( RawSock == INVALID_SOCKET )
{
return FALSE ;
}
// 設定接收超時為1秒
int nTimeout = networktest->m_time ;
int ret = ::setsockopt ( RawSock, SOL_SOCKET,SO_RCVTIMEO, (char*)&nTimeout, sizeof(nTimeout));
char szRecvBuf [ DEF_BUF_SIZE] ;
SOCKADDR_IN SourSockAddr ;
SOCKADDR_IN DestSockAddr ;
DestSockAddr.sin_family = AF_INET;
inet_addr(networktest->szDestIp);
DestSockAddr.sin_addr.s_addr = inet_addr(networktest->szDestIp) ;
DestSockAddr.sin_port = htons ( 0 ) ;
char m_str_start[128];
if(networktest->index_stop==true)
{
networktest->m_pinglist.ResetContent();
wsprintf(m_str_start,"正在ping [%s]",networktest->szDestIp);
networktest->m_pinglist.AddString(m_str_start);
networktest->index_stop=false;
}
pICMPHeader->nCheckSum = 0 ; // 初始時校驗值為0
pICMPHeader->nSequence = i ; // 序號
pICMPHeader->nTimeStamp = ::GetTickCount() ;// 當前時間
// 計算校驗值,校驗值要在ICMP資料報創建完才能計算
pICMPHeader->nCheckSum = networktest->GetCheckSum ( (LPBYTE)ICMPPack, ICMP_HEADER_SIZE + networktest->m_packet ) ;//
// 發送ICMP資料包
int nRet = ::sendto ( RawSock, ICMPPack, ICMP_HEADER_SIZE + networktest->m_packet,0,(SOCKADDR*)&DestSockAddr, sizeof(DestSockAddr) ) ;//
if ( nRet == SOCKET_ERROR )
{
networktest->m_pinglist.AddString ( "sendto error!\n" ) ;
return FALSE ;
}
// 接收ICMP回應
int nLen = sizeof(SourSockAddr) ;
nRet = ::recvfrom ( RawSock, szRecvBuf, DEF_BUF_SIZE,0,(SOCKADDR*)&SourSockAddr, &nLen ) ;
if ( nRet == SOCKET_ERROR )
{
if ( ::WSAGetLastError() == WSAETIMEDOUT )
{
networktest->m_pinglist.AddString ( "Request Timeout\n" ) ;
continue ;
}
else
{
networktest->m_pinglist.AddString ( "recvfrom error!\n" ) ;
return FALSE ;
}
}
// 計算ICMP資料報的時間差
int nTime = ::GetTickCount() - pICMPHeader->nTimeStamp ;
int nRealSize = nRet - IP_HEADER_SIZE - ICMP_HEADER_SIZE ;
if ( nRealSize < 0 )
{
networktest->m_pinglist.AddString ( "To less recv bytes!\n" );
continue ;
}
// 檢測是否當前所發出的ICMP回應包
PICMP_HEADER pRecvHeader = (PICMP_HEADER)(szRecvBuf+IP_HEADER_SIZE);
CString str_all;
CString m_TTL;
if(networktest->m_check1.GetCheck())
{
m_TTL.Format("TTL=%d",nRet);
}
else
m_TTL="";
CString m_replaytime;
if(networktest->m_check2.GetCheck())
{
m_replaytime.Format("time=%dms ",nTime);
}
else
m_replaytime="";
CString m_packetsize;
if(networktest->m_check3.GetCheck())
{
m_packetsize.Format("bytes=%d ",nRealSize);
}
else
m_packetsize="";
CString m_ipreplay;
if(networktest->m_check4.GetCheck())
{
m_ipreplay.Format("replay[%d] from %s :",networktest->m_index,inet_ntoa(SourSockAddr.sin_addr));
}
else
m_ipreplay="";
str_all=m_ipreplay+m_packetsize+m_replaytime+m_TTL;
networktest->m_index++;
networktest->m_pinglist.AddString(str_all);
networktest->UpdateWindow();//立馬重繪顯示
Sleep(1000) ;//
i++;
closesocket(RawSock) ;
WSACleanup();
}//回圈
uj5u.com熱心網友回復:
僅供參考:#include <windows.h>
#include <stdio.h>
#include <string.h>
char YN(int k) {
FILE *f;
char fn[40];
char ln[80];
char yn;
int n;
yn='N';
sprintf(fn,"d:\\ping%d.txt",k);
f=fopen(fn,"r");
if (NULL!=f) {
n=0;
while (1) {
if (NULL==fgets(ln,80,f)) break;//
if (strstr(ln,"ms ")) {
yn='Y';
break;//
}
n++;
if (n>=4) break;//
}
fclose(f);
}
return yn;
}
void main(int argc,char **argv) {
char cmdstr[256];
int i;
int IP[3];
char c;
if (argc<2) {
USAGE:
printf("Usage example:\n %s 192.168.60.\nto test 192.168.60.1-254\n",argv[0]);
return;
}
if (4==sscanf(argv[1],"%d.%d.%d%c",&IP[0],&IP[1],&IP[2],&c)) {
if (0<=IP[0] && IP[0]<=255
&& 0<=IP[1] && IP[1]<=255
&& 0<=IP[2] && IP[2]<=255
&& '.'==c) {
for (i=1;i<255;i++) {
sprintf(cmdstr,"cmd /c ping %s%d -n 1 -w 1000 >d:\\ping%d.txt",argv[1],i,i);
WinExec(cmdstr,SW_HIDE);
}
Sleep(3000);
for (i=1;i<255;i++) {
printf("%c %s%d\n",YN(i),argv[1],i);
}
Sleep(3000);
WinExec("cmd /c del /q d:\\ping*.txt",SW_HIDE);
} else goto USAGE;
} else goto USAGE;
}
uj5u.com熱心網友回復:
正解在這里:方案1、自己寫ping函式。這樣成功或失敗就很容易分析了吧。
方案2、如果你非要用CMD的ping命令,那么,給你的建議是使用管道技術。就是創建一個緩沖區,將子行程ping命令的輸出轉向到你的緩沖區,然后分析緩沖區內的文本即可。同時還可以隱藏ping視窗。
uj5u.com熱心網友回復:
管道技術請自行百度,下面的供參考。很久以前寫的。
啟動一個Windows控制臺行程,并將其輸出轉向。
截獲目標行程輸出的方式:
1、等待目標行程結束后讀取緩沖區,并更新。
2、隨時讀取緩沖區并追加更新到指定輸出。(但每次讀之前需要清除緩沖區,否則輸出重疊)
unsigned long SomeThread( LPVOID pVoid )
{
char Buffer [ 4096 ];
DWORD dwExit = 1;
HANDLE hReadPipe = NULL;
HANDLE hWritePipe = NULL;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof( SECURITY_ATTRIBUTES );
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
CString szCurPath = pDlg->GetFilePath();
STARTUPINFO StartupInfo = { sizeof(StartupInfo) };
PROCESS_INFORMATION ProcessInfo = { 0 };
TCHAR szCommandLine[ 256 ]; // = _T("c:\\windows\\system32\\cmd.exe /c dir");
_tcscpy_s( szCommandLine, 256, ( szCurPath + _T("VPNRel.EXE")));
ZeroMemory( Buffer, 4096 );
if( ! CreatePipe( &hReadPipe, &hWritePipe, &sa, 0 ))
{
goto EXIT_THREAD;
}
StartupInfo.cb = sizeof( STARTUPINFO );
GetStartupInfo( &StartupInfo );
StartupInfo.hStdError = hWritePipe;
StartupInfo.hStdOutput = hWritePipe;
StartupInfo.wShowWindow = SW_HIDE;
StartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if( ! CreateProcess( NULL, szCommandLine, NULL, NULL, TRUE, 0, NULL, szCurPath, &StartupInfo, &ProcessInfo ))
{
goto EXIT_THREAD;
}
// - 創建目標行程成功,開始等待目標行程結束并監視其輸出
// ----------------------------目標行程輸出-------------------------------
CloseHandle( hWritePipe );
hWritePipe = NULL;
while( dwExit )
{
DWORD dwWait = WaitForSingleObject( ProcessInfo.hProcess, 200 );
DWORD dwReaded;
ZeroMemory( Buffer, sizeof( Buffer )); // Cleaer Buffer.
if( ReadFile( hReadPipe, Buffer, 4095, &dwReaded, NULL ) == false )
{
if( dwWait == WAIT_TIMEOUT )
continue;
else
break;
}
else
{
#ifdef _UNICODE
TCHAR szWBuffer[ 4096 ];
ZeroMemory( szWBuffer, sizeof( TCHAR ) * 4096 );
MultiByteToWideChar( CP_ACP, 0, Buffer, -1, szWBuffer, 4095 );
APPEND( szWBuffer ); // == m_strSomeEdit += szWBuffer; UpdateData( false );
#else
APPEND( Buffer ); // == m_strSomeEdit += Buffer; UpdateData( false );
#endif
}
if( dwWait == WAIT_OBJECT_0 )
break;
}
//--------------------------目標行程已經結束------------------------------
EXIT_THREAD:
if( ProcessInfo.hProcess != NULL )
CloseHandle( ProcessInfo.hProcess );
if( hWritePipe != NULL )
CloseHandle( hWritePipe );
if( hReadPipe != NULL )
CloseHandle( hReadPipe );
pDlg->m_hThread = NULL;
return 0;
}
uj5u.com熱心網友回復:
你的正解,雖然我找到方法了,還是很感謝各位回帖的大神
uj5u.com熱心網友回復:
int i=0;
NetworkTest *networktest = (NetworkTest *)pParam;
networktest->m_pinglist.ResetContent();
// 創建ICMP回顯請求包
// char *ICMPPack;
// ICMPPack=new char[networktest->packet];
while (networktest->m_stop)//networktest->m_index
{
char ICMPPack[1024] = {0} ;
PICMP_HEADER pICMPHeader = (PICMP_HEADER)ICMPPack ;
pICMPHeader->bType = 8 ;
pICMPHeader->bCode = 0 ;
pICMPHeader->nId = (USHORT)::GetCurrentProcessId() ;
pICMPHeader->nCheckSum = 0 ;
pICMPHeader->nTimeStamp = 0 ;
memset ( (&ICMPPack[ICMP_HEADER_SIZE]), 'E',ICMP_HEADER_SIZE + networktest->m_packet) ; // 填充資料部分,內容任意
// 初始化WinSock庫
WORD wVersionRequested = MAKEWORD( 2, 2 );
WSADATA wsaData;
if ( WSAStartup( wVersionRequested, &wsaData ) != 0 )
return FALSE ;
// 創建原始套接字
SOCKET RawSock = socket ( AF_INET, SOCK_RAW, IPPROTO_ICMP ) ;
if ( RawSock == INVALID_SOCKET )
{
return FALSE ;
}
// 設定接收超時為1秒
int nTimeout = networktest->m_time ;
int ret = ::setsockopt ( RawSock, SOL_SOCKET,SO_RCVTIMEO, (char*)&nTimeout, sizeof(nTimeout));
char szRecvBuf [ DEF_BUF_SIZE] ;
SOCKADDR_IN SourSockAddr ;
SOCKADDR_IN DestSockAddr ;
DestSockAddr.sin_family = AF_INET;
inet_addr(networktest->szDestIp);
DestSockAddr.sin_addr.s_addr = inet_addr(networktest->szDestIp) ;
DestSockAddr.sin_port = htons ( 0 ) ;
char m_str_start[128];
if(networktest->index_stop==true)
{
networktest->m_pinglist.ResetContent();
wsprintf(m_str_start,"正在ping [%s]",networktest->szDestIp);
networktest->m_pinglist.AddString(m_str_start);
networktest->index_stop=false;
}
pICMPHeader->nCheckSum = 0 ; // 初始時校驗值為0
pICMPHeader->nSequence = i ; // 序號
pICMPHeader->nTimeStamp = ::GetTickCount() ;// 當前時間
// 計算校驗值,校驗值要在ICMP資料報創建完才能計算
pICMPHeader->nCheckSum = networktest->GetCheckSum ( (LPBYTE)ICMPPack, ICMP_HEADER_SIZE + networktest->m_packet ) ;//
// 發送ICMP資料包
int nRet = ::sendto ( RawSock, ICMPPack, ICMP_HEADER_SIZE + networktest->m_packet,0,(SOCKADDR*)&DestSockAddr, sizeof(DestSockAddr) ) ;//
if ( nRet == SOCKET_ERROR )
{
networktest->m_pinglist.AddString ( "sendto error!\n" ) ;
return FALSE ;
}
// 接收ICMP回應
int nLen = sizeof(SourSockAddr) ;
nRet = ::recvfrom ( RawSock, szRecvBuf, DEF_BUF_SIZE,0,(SOCKADDR*)&SourSockAddr, &nLen ) ;
if ( nRet == SOCKET_ERROR )
{
if ( ::WSAGetLastError() == WSAETIMEDOUT )
{
networktest->m_pinglist.AddString ( "Request Timeout\n" ) ;
continue ;
}
else
{
networktest->m_pinglist.AddString ( "recvfrom error!\n" ) ;
return FALSE ;
}
}
// 計算ICMP資料報的時間差
int nTime = ::GetTickCount() - pICMPHeader->nTimeStamp ;
int nRealSize = nRet - IP_HEADER_SIZE - ICMP_HEADER_SIZE ;
if ( nRealSize < 0 )
{
networktest->m_pinglist.AddString ( "To less recv bytes!\n" );
continue ;
}
// 檢測是否當前所發出的ICMP回應包
PICMP_HEADER pRecvHeader = (PICMP_HEADER)(szRecvBuf+IP_HEADER_SIZE);
CString str_all;
CString m_TTL;
if(networktest->m_check1.GetCheck())
{
m_TTL.Format("TTL=%d",nRet);
}
else
m_TTL="";
CString m_replaytime;
if(networktest->m_check2.GetCheck())
{
m_replaytime.Format("time=%dms ",nTime);
}
else
m_replaytime="";
CString m_packetsize;
if(networktest->m_check3.GetCheck())
{
m_packetsize.Format("bytes=%d ",nRealSize);
}
else
m_packetsize="";
CString m_ipreplay;
if(networktest->m_check4.GetCheck())
{
m_ipreplay.Format("replay[%d] from %s :",networktest->m_index,inet_ntoa(SourSockAddr.sin_addr));
}
else
m_ipreplay="";
str_all=m_ipreplay+m_packetsize+m_replaytime+m_TTL;
networktest->m_index++;
networktest->m_pinglist.AddString(str_all);
networktest->UpdateWindow();//立馬重繪顯示
Sleep(1000) ;//
i++;
closesocket(RawSock) ;
WSACleanup();
}//回圈
這是模擬Ping的底層實作嗎
uj5u.com熱心網友回復:
管道技術加上createprocess可以解決uj5u.com熱心網友回復:
樓上的大佬們能講下ping的缺陷嗎,為何還需要開行程設緩沖區呢?擔心ping對程式主執行緒有影響可以開個執行緒來ping,這樣有什么缺陷呢?uj5u.com熱心網友回復:
樓上的大佬們能講下ping的缺陷嗎,為何還需要開行程設緩沖區呢?擔心ping對程式主執行緒有影響可以開個執行緒來ping,這樣有什么缺陷呢?
參考《Unix編程藝術》
uj5u.com熱心網友回復:
檢查IP地址是否在線,和是否連接到本機是不同的兩個概念。建議擼主先了解清楚了需求再提問。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/98300.html
標籤:網絡編程
上一篇:VS2017 C++入門
