如何判断局域网是否连通? 当局域网断开时,操作系统任务栏会有一个网络断开的图标出现,如何编程实现对局域网是否连通的判断呢? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 http://expert.csdn.net/Expert/topic/1855/1855796.xml?temp=.3466608 基于ICMP的PING,和基于SOCKET的通讯程序都可以用来检测 以上方法均不适用,我的程序将在以下环境中使用:1.局域网中没有网关和域,不能连上Internet2.所有计算机都没有自己指定IP,也没有计算机专门提供分配IP的服务3.所有计算机都拒绝 ping3.要求在计算机启动后,没有访问任何网络资源,也没有其他计算机来访问的前提下(操作系统自己访问网络,不受该限制)判断局域网是否连通.请问高手,该如何实现? 对于3:可以把程序写成服务,设置为自动启动!//检查Internet 的连接性BOOL CheckOffline(){ DWORD ConnectState; DWORD StateSize; StateSize=sizeof(ConnectState); BOOL result=false; //检查当前的Internet设置是否可用 if(InternetQueryOption(NULL,INTERNET_OPTION_CONNECTED_STATE,&ConnectState,StateSize) { if(ConnectState & INTERNET_STATE_DISCONNECTED != 2) { //检查连接到internet了吗? if InternetheckConnection('http://www.sohu,com/'1,0) GetDlgItem(IDC_EDIT1)->SetDlgItemText(IDC_EDIT1,_T("Connected")); else 'DisConnected' result = true; } }return result;} 用原始套接字实现,发送SYN请求,接收到ACK就表示连通,而且很快速、很隐蔽。 上面那个有点错误!//检查Internet 的连接性BOOL CMyGoodsDlg::CheckOnline(){ DWORD ConnectState; DWORD StateSize; StateSize=sizeof(ConnectState); BOOL result=false; //检查当前的Internet设置是否可用 if(InternetQueryOption(NULL,INTERNET_OPTION_CONNECTED_STATE,&ConnectState,&StateSize)) { if((ConnectState & INTERNET_STATE_DISCONNECTED) != 2) { //检查连接到internet了吗? if (InternetCheckConnection("http://www.sohu.com/",1,0)) { GetDlgItem(IDC_TESTALT)->SetDlgItemText(IDC_TESTALT,_T("Connected")); result = true; } else GetDlgItem(IDC_TESTALT)->SetDlgItemText(IDC_TESTALT,_T("DisConnected")); } } return result;}//是否上网 //INTERNET_CONNECTED_INFOvoid CMyGoodsDlg::OnIsonline() { CheckOnline(); return ; DWORD flags; //上网方式 InternetGetConnectedState(&flags,0); if( (flags & INTERNET_CONNECTION_MODEM) || (flags & INTERNET_CONNECTION_LAN) ||(flags & INTERNET_CONNECTION_PROXY)) { TCHAR bufferpath[_MAX_PATH]; PTCHAR pBuf; pBuf=bufferpath; GetSystemDirectory(pBuf,_MAX_PATH); PTCHAR pPos=_tcsstr(pBuf,_T("System32")); VERIFY((pPos-pBuf-1)>0); bufferpath[pPos-pBuf-1]='\0'; _tcscat(pBuf,"\\Media\\Windows 登录音.wav"); //StrTrim(pBuf,_T("system32")); //这个需要:Shlwapi.h CString cs=_T( "已上网"); //GetDlgItem(IDC_ISONLINE)-> SetDlgItemText(IDC_ISONLINE, cs); sndPlaySound(pBuf,SND_SYNC); } else GetDlgItem(IDC_TESTALT)->SetWindowText(_T("未上网"));}//下面这段是MSDN的如何设置代理服务器信息The following sample demonstrates how to set proxy information for a LAN connection.BOOL SetConnectionOptions(){ INTERNET_PER_CONN_OPTION_LIST list; BOOL bReturn; DWORD dwBufSize = sizeof(list); // Fill out list struct. list.dwSize = sizeof(list); // NULL == LAN, otherwise connectoid name. list.pszConnection = NULL; // Set three options. list.dwOptionCount = 3; list.pOptions = new INTERNET_PER_CONN_OPTION[3]; // Make sure the memory was allocated. if(NULL == list.pOptions) { // Return FALSE if the memory wasn't allocated. return FALSE; } // Set flags. list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS; list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT | PROXY_TYPE_PROXY; // Set proxy name. list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER; list.pOptions[1].Value.pszValue = "http://proxy:80"; // Set proxy override. list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS; list.pOptions[2].Value.pszValue = "local"; // Set the options on the connection. bReturn = InternetSetOption(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); // Free the allocated memory. delete [] list.pOptions; return bReturn;} Ping就可以,开一个线程做Ping,下面是封装好的发送数据包的Ping类// UDPPing.h: interface for the CUDPPing class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_UDPPING_H__A28CF5A0_3845_406C_830B_C8E583080AF5__INCLUDED_)#define AFX_UDPPING_H__A28CF5A0_3845_406C_830B_C8E583080AF5__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000//使用的Winsock版本是2.2//#include<winsock2.h>//对发送协议结构数据格式的定义#define REQ_DATASIZE 32 //#define WM_MSG_STATUS WM_USER + 0x0100//#define WM_MSG_PINGSTOP WM_USER + 0x0101typedef struct tagIPHDR{ u_char VIHL; // Version and IHL u_char TOS; // Type Of Service short TotLen; // Total Length short ID; // Identification short FlagOff; // Flags and Fragment Offset u_char TTL; // Time To Live u_char Protocol; // Protocol u_short Checksum; // Checksum struct in_addr iaSrc; // Internet Address - Source struct in_addr iaDst; // Internet Address - Destination}IPHDR, *PIPHDR;// ICMP Header - RFC 792typedef struct tagICMPHDR{ u_char Type; // Type u_char Code; // Code u_short Checksum; // Checksum u_short ID; // Identification u_short Seq; // Sequence char Data; // Data}ICMPHDR, *PICMPHDR;#define REQ_DATASIZE 32 // Echo Request Data size#define ICMP_ECHOREQ 8// ICMP Echo Requesttypedef struct tagECHOREQUEST{ ICMPHDR icmpHdr; DWORD dwTime; char cData[REQ_DATASIZE];}ECHOREQUEST, *PECHOREQUEST;// ICMP Echo Replytypedef struct tagECHOREPLY{ IPHDR ipHdr; ECHOREQUEST echoRequest; char cFiller[256];}ECHOREPLY, *PECHOREPLY;#include "BasePing.h"class CUDPPing : public CBasePing {public: private: u_short in_cksum(u_short *addr, int len); DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL); int SendEchoRequest(SOCKET s, LPSOCKADDR_IN lpstToAddr); int WaitForEchoReply(SOCKET s); SOCKET m_rawSocket; int m_iRet;public: virtual void Serialize(CArchive & ar); void Close(); bool Open(); bool Ping(LPCTSTR pStrHostName, DWORD nPingTimeout); CUDPPing(); virtual ~CUDPPing();protected: DECLARE_SERIAL(CUDPPing);};#endif // !defined(AFX_UDPPING_H__A28CF5A0_3845_406C_830B_C8E583080AF5__INCLUDED_) // UDPPing.cpp: implementation of the CUDPPing class.////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "UDPPing.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////IMPLEMENT_SERIAL(CUDPPing,CObject,1);CUDPPing::CUDPPing(){ m_type=2;}CUDPPing::~CUDPPing(){}bool CUDPPing::Ping(LPCTSTR pStrHostName, DWORD nPingTimeout){ struct sockaddr_in saDest; struct sockaddr_in saSrc; LPHOSTENT lpHost; CString str; DWORD dwTimeSent,dwElapsed; u_char cTTL; long m_laddr; //清零 m_laddr = inet_addr((CString)pStrHostName); if (m_laddr == INADDR_NONE) { lpHost = gethostbyname((CString)pStrHostName); if (lpHost == NULL) { return FALSE; } saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr)); } else { saDest.sin_addr.s_addr =m_laddr; } saDest.sin_family = AF_INET; saDest.sin_port = 0; //PING SendEchoRequest(m_rawSocket, &saDest); m_iRet = WaitForEchoReply(m_rawSocket); if (!m_iRet) { return FALSE; } else { // 刷新回应 dwTimeSent = RecvEchoReply(m_rawSocket, &saSrc, &cTTL); // 计算剩余时间 dwElapsed = GetTickCount() - dwTimeSent; } return TRUE;}int CUDPPing::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));}int CUDPPing::SendEchoRequest(SOCKET s, LPSOCKADDR_IN lpstToAddr){ static ECHOREQUEST echoReq; static nId = 1; static nSeq = 1; int nRet; //填充请求 echoReq.icmpHdr.Type = ICMP_ECHOREQ; echoReq.icmpHdr.Code = 0; echoReq.icmpHdr.Checksum = 0; echoReq.icmpHdr.ID = nId++; echoReq.icmpHdr.Seq = nSeq++; // 填充测试用的数据 for (nRet = 0; nRet < REQ_DATASIZE; nRet++) echoReq.cData[nRet] = ' '+nRet; // Save tick count when sent echoReq.dwTime = GetTickCount(); // 把数据放入包中并接受检查 echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST)); //发送请求的显示信息 nRet = sendto(s, /* socket */ (LPSTR)&echoReq, /* 缓冲 */ sizeof(ECHOREQUEST), 0, /* 标志 */ (LPSOCKADDR)lpstToAddr, /* 定义 */ sizeof(SOCKADDR_IN)); /* 地址长度 */ return (nRet);}DWORD CUDPPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL){ ECHOREPLY echoReply; int nRet; int nAddrLen = sizeof(struct sockaddr_in); // 刷新请求连接的信息 nRet = recvfrom(s, // socket (LPSTR)&echoReply, // 缓冲 sizeof(ECHOREPLY), // 缓冲大小 0, // 标志 (LPSOCKADDR)lpsaFrom, // 源地址 &nAddrLen); // 指向地址长度的指针 // 检测返回的信息 // 返回 time sent and IP TTL *pTTL = echoReply.ipHdr.TTL; return(echoReply.echoRequest.dwTime); }u_short CUDPPing::in_cksum(u_short *addr, int len){ register int nleft = len; register u_short *w = addr; register u_short answer; register int sum = 0; /* * 由于十进制比较简单采用32位 * 采用可延伸的16位进制。 * 当需要时从高16位可扩展至低16位. */ while( nleft > 1 ) { sum += *w++; nleft -= 2; } /* 如果有必要。提出一字节 */ if( nleft == 1 ) { u_short u = 0; *(u_char *)(&u) = *(u_char *)w ; sum += u; } /* * 从高16位到低16位 */ sum = (sum >> 16) + (sum & 0xffff); /* 添加高16位到低16位 */ sum += (sum >> 16); answer = ~sum; /* 截至16位 */ return (answer);}bool CUDPPing::Open(){ m_rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); return TRUE;}void CUDPPing::Close(){ closesocket(m_rawSocket);}void CUDPPing::Serialize(CArchive &ar){ if (ar.IsStoring()) { ar<<m_iPingTimes<<m_priority ; // TODO: add storing code here } else { ar>>m_iPingTimes>>m_priority ; // TODO: add loading code here }} 转自驱动开发网发信人: rain (夜猫子大王), 信区: SysInternals标 题: Re: 请问实时发现网络down掉的原理?(转载)发信站: 武汉白云黄鹤站 (2001年03月31日09:57:05 星期六), 转信实时检测网线被拔掉是需要网卡设备驱动程序支持的,如果驱动程序不支持是无法实现的,NDIS4要求设备驱动程序最好提供CheckForHangHandler回调函数。2000会每隔2秒钟调用此函数。驱动程序在此函数中检查网卡连线状态,如果发生了改变,即拔去了网线或接上了网线,驱动程序就会调用NdisMIndicateStatus通知所有的上层NDIS协议驱动程序.其中: NDIS_STATUS_MEDIA_DISCONNECT 指示网线被拔掉,NDIS_STATUS_MEDIA_CONNECT 指示网线被接上NDIS_STATUS_LINK_SPEED_CHANGE 指示网卡速度改变,10/100自适应网卡才有。网卡一般都有 status register 指示当然的连线状态,也有网卡是通过获得 led status 来知道当前的连线状态的,即绿灯亮表示连线,灭表示没有。有些网卡拔掉或接上网线时会产生中断,在中断处理程序中一般也检测网络连线状态并调用NdisMIndicateStatus,这样连线状态在2000中就实时反应出来了,否则会在2秒钟内,即NDIS调用CheckForHangHandler后。这个功能是微软在PC97规范中定义的,所以ndis3没有这个功能。linux对这个没有要求,novell netware对这个有要求,其它的操作系统我也不清楚。 除法和求幂乱码 socket 端口复用!!谢谢!! 关于Ontimer()的问题 请教关于《Windows核心编程》一书中的例子,再线!!! CIPAddressCtrl 关于ActiveX aggregate的问题 请问,我在一个文件中声明了一个全局变量,怎么在其它文件中使用? Bardo(巴顿):请进入领分............................... 多进程间directsound硬件混音模式下通知到达异常,大家有碰到过吗? 如何在状态栏上加进度条。 请问如何判断一个字符串是小数? 如何判断局域网是否连通?
1.局域网中没有网关和域,不能连上Internet
2.所有计算机都没有自己指定IP,也没有计算机专门提供分配IP的服务
3.所有计算机都拒绝 ping
3.要求在计算机启动后,没有访问任何网络资源,也没有其他计算机来访问的前提下(操作系统自己访问网络,不受该限制)判断局域网是否连通.请问高手,该如何实现?
BOOL CheckOffline()
{
DWORD ConnectState;
DWORD StateSize;
StateSize=sizeof(ConnectState);
BOOL result=false;
//检查当前的Internet设置是否可用
if(InternetQueryOption(NULL,INTERNET_OPTION_CONNECTED_STATE,&ConnectState,StateSize)
{
if(ConnectState & INTERNET_STATE_DISCONNECTED != 2)
{
//检查连接到internet了吗?
if InternetheckConnection('http://www.sohu,com/'1,0)
GetDlgItem(IDC_EDIT1)->SetDlgItemText(IDC_EDIT1,_T("Connected"));
else 'DisConnected'
result = true;
}
}
return result;
}
BOOL CMyGoodsDlg::CheckOnline()
{
DWORD ConnectState;
DWORD StateSize;
StateSize=sizeof(ConnectState);
BOOL result=false;
//检查当前的Internet设置是否可用
if(InternetQueryOption(NULL,INTERNET_OPTION_CONNECTED_STATE,&ConnectState,&StateSize))
{
if((ConnectState & INTERNET_STATE_DISCONNECTED) != 2)
{
//检查连接到internet了吗?
if (InternetCheckConnection("http://www.sohu.com/",1,0))
{
GetDlgItem(IDC_TESTALT)->SetDlgItemText(IDC_TESTALT,_T("Connected"));
result = true;
}
else GetDlgItem(IDC_TESTALT)->SetDlgItemText(IDC_TESTALT,_T("DisConnected"));
}
}
return result;
}
//是否上网 //INTERNET_CONNECTED_INFO
void CMyGoodsDlg::OnIsonline()
{ CheckOnline();
return ; DWORD flags; //上网方式
InternetGetConnectedState(&flags,0);
if( (flags & INTERNET_CONNECTION_MODEM) || (flags & INTERNET_CONNECTION_LAN) ||(flags & INTERNET_CONNECTION_PROXY)) {
TCHAR bufferpath[_MAX_PATH];
PTCHAR pBuf;
pBuf=bufferpath;
GetSystemDirectory(pBuf,_MAX_PATH);
PTCHAR pPos=_tcsstr(pBuf,_T("System32"));
VERIFY((pPos-pBuf-1)>0);
bufferpath[pPos-pBuf-1]='\0';
_tcscat(pBuf,"\\Media\\Windows 登录音.wav");
//StrTrim(pBuf,_T("system32")); //这个需要:Shlwapi.h
CString cs=_T( "已上网");
//GetDlgItem(IDC_ISONLINE)->
SetDlgItemText(IDC_ISONLINE, cs);
sndPlaySound(pBuf,SND_SYNC);
}
else GetDlgItem(IDC_TESTALT)->SetWindowText(_T("未上网"));
}
//下面这段是MSDN的如何设置代理服务器信息
The following sample demonstrates how to set proxy information for a LAN connection.BOOL SetConnectionOptions()
{
INTERNET_PER_CONN_OPTION_LIST list;
BOOL bReturn;
DWORD dwBufSize = sizeof(list); // Fill out list struct.
list.dwSize = sizeof(list); // NULL == LAN, otherwise connectoid name.
list.pszConnection = NULL; // Set three options.
list.dwOptionCount = 3;
list.pOptions = new INTERNET_PER_CONN_OPTION[3]; // Make sure the memory was allocated.
if(NULL == list.pOptions)
{
// Return FALSE if the memory wasn't allocated.
return FALSE;
} // Set flags.
list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT |
PROXY_TYPE_PROXY; // Set proxy name.
list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
list.pOptions[1].Value.pszValue = "http://proxy:80"; // Set proxy override.
list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
list.pOptions[2].Value.pszValue = "local"; // Set the options on the connection.
bReturn = InternetSetOption(NULL,
INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize); // Free the allocated memory.
delete [] list.pOptions; return bReturn;
}
// UDPPing.h: interface for the CUDPPing class.
//
//////////////////////////////////////////////////////////////////////#if !defined(AFX_UDPPING_H__A28CF5A0_3845_406C_830B_C8E583080AF5__INCLUDED_)
#define AFX_UDPPING_H__A28CF5A0_3845_406C_830B_C8E583080AF5__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//使用的Winsock版本是2.2
//#include<winsock2.h>
//对发送协议结构数据格式的定义
#define REQ_DATASIZE 32
//#define WM_MSG_STATUS WM_USER + 0x0100
//#define WM_MSG_PINGSTOP WM_USER + 0x0101
typedef struct tagIPHDR
{
u_char VIHL; // Version and IHL
u_char TOS; // Type Of Service
short TotLen; // Total Length
short ID; // Identification
short FlagOff; // Flags and Fragment Offset
u_char TTL; // Time To Live
u_char Protocol; // Protocol
u_short Checksum; // Checksum
struct in_addr iaSrc; // Internet Address - Source
struct in_addr iaDst; // Internet Address - Destination
}IPHDR, *PIPHDR;
// ICMP Header - RFC 792
typedef struct tagICMPHDR
{
u_char Type; // Type
u_char Code; // Code
u_short Checksum; // Checksum
u_short ID; // Identification
u_short Seq; // Sequence
char Data; // Data
}ICMPHDR, *PICMPHDR;
#define REQ_DATASIZE 32 // Echo Request Data size
#define ICMP_ECHOREQ 8// ICMP Echo Request
typedef struct tagECHOREQUEST
{
ICMPHDR icmpHdr;
DWORD dwTime;
char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;
// ICMP Echo Reply
typedef struct tagECHOREPLY
{
IPHDR ipHdr;
ECHOREQUEST echoRequest;
char cFiller[256];
}ECHOREPLY, *PECHOREPLY;
#include "BasePing.h"class CUDPPing : public CBasePing
{
public:
private:
u_short in_cksum(u_short *addr, int len);
DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL);
int SendEchoRequest(SOCKET s, LPSOCKADDR_IN lpstToAddr);
int WaitForEchoReply(SOCKET s);
SOCKET m_rawSocket;
int m_iRet;
public:
virtual void Serialize(CArchive & ar);
void Close();
bool Open(); bool Ping(LPCTSTR pStrHostName, DWORD nPingTimeout);
CUDPPing();
virtual ~CUDPPing();
protected:
DECLARE_SERIAL(CUDPPing);};#endif // !defined(AFX_UDPPING_H__A28CF5A0_3845_406C_830B_C8E583080AF5__INCLUDED_)
//
//////////////////////////////////////////////////////////////////////#include "stdafx.h"
#include "UDPPing.h"#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_SERIAL(CUDPPing,CObject,1);
CUDPPing::CUDPPing()
{ m_type=2;
}CUDPPing::~CUDPPing()
{}bool CUDPPing::Ping(LPCTSTR pStrHostName, DWORD nPingTimeout)
{
struct sockaddr_in saDest;
struct sockaddr_in saSrc;
LPHOSTENT lpHost;
CString str;
DWORD dwTimeSent,dwElapsed;
u_char cTTL;
long m_laddr;
//清零
m_laddr = inet_addr((CString)pStrHostName);
if (m_laddr == INADDR_NONE)
{
lpHost = gethostbyname((CString)pStrHostName);
if (lpHost == NULL)
{
return FALSE;
}
saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
}
else
{
saDest.sin_addr.s_addr =m_laddr;
}
saDest.sin_family = AF_INET;
saDest.sin_port = 0;
//PING
SendEchoRequest(m_rawSocket, &saDest);
m_iRet = WaitForEchoReply(m_rawSocket);
if (!m_iRet)
{
return FALSE;
}
else
{
// 刷新回应 dwTimeSent = RecvEchoReply(m_rawSocket, &saSrc, &cTTL); // 计算剩余时间
dwElapsed = GetTickCount() - dwTimeSent;
}
return TRUE;
}int CUDPPing::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));
}int CUDPPing::SendEchoRequest(SOCKET s, LPSOCKADDR_IN lpstToAddr)
{
static ECHOREQUEST echoReq;
static nId = 1;
static nSeq = 1;
int nRet; //填充请求
echoReq.icmpHdr.Type = ICMP_ECHOREQ;
echoReq.icmpHdr.Code = 0;
echoReq.icmpHdr.Checksum = 0;
echoReq.icmpHdr.ID = nId++;
echoReq.icmpHdr.Seq = nSeq++; // 填充测试用的数据
for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
echoReq.cData[nRet] = ' '+nRet; // Save tick count when sent
echoReq.dwTime = GetTickCount(); // 把数据放入包中并接受检查
echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST)); //发送请求的显示信息
nRet = sendto(s, /* socket */
(LPSTR)&echoReq, /* 缓冲 */
sizeof(ECHOREQUEST),
0, /* 标志 */
(LPSOCKADDR)lpstToAddr, /* 定义 */
sizeof(SOCKADDR_IN)); /* 地址长度 */
return (nRet);
}DWORD CUDPPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL)
{
ECHOREPLY echoReply;
int nRet;
int nAddrLen = sizeof(struct sockaddr_in); // 刷新请求连接的信息
nRet = recvfrom(s, // socket
(LPSTR)&echoReply, // 缓冲
sizeof(ECHOREPLY), // 缓冲大小
0, // 标志
(LPSOCKADDR)lpsaFrom, // 源地址
&nAddrLen); // 指向地址长度的指针 // 检测返回的信息 // 返回 time sent and IP TTL
*pTTL = echoReply.ipHdr.TTL; return(echoReply.echoRequest.dwTime); }u_short CUDPPing::in_cksum(u_short *addr, int len)
{ register int nleft = len;
register u_short *w = addr;
register u_short answer;
register int sum = 0; /*
* 由于十进制比较简单采用32位
* 采用可延伸的16位进制。
* 当需要时从高16位可扩展至低16位.
*/
while( nleft > 1 )
{
sum += *w++;
nleft -= 2;
} /* 如果有必要。提出一字节 */
if( nleft == 1 ) {
u_short u = 0; *(u_char *)(&u) = *(u_char *)w ;
sum += u;
} /*
* 从高16位到低16位
*/
sum = (sum >> 16) + (sum & 0xffff); /* 添加高16位到低16位 */
sum += (sum >> 16);
answer = ~sum; /* 截至16位 */
return (answer);
}
bool CUDPPing::Open()
{
m_rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
return TRUE;
}void CUDPPing::Close()
{
closesocket(m_rawSocket);
}void CUDPPing::Serialize(CArchive &ar)
{
if (ar.IsStoring())
{
ar<<m_iPingTimes<<m_priority ; // TODO: add storing code here
}
else
{
ar>>m_iPingTimes>>m_priority ; // TODO: add loading code here
}
}
发信人: rain (夜猫子大王), 信区: SysInternals
标 题: Re: 请问实时发现网络down掉的原理?(转载)
发信站: 武汉白云黄鹤站 (2001年03月31日09:57:05 星期六), 转信实时检测网线被拔掉是需要网卡设备驱动程序支持的,
如果驱动程序不支持是无法实现的,NDIS4要求设备驱动程序
最好提供CheckForHangHandler回调函数。2000会每隔2秒钟
调用此函数。驱动程序在此函数中检查网卡连线状态,
如果发生了改变,即拔去了网线或接上了网线,
驱动程序就会调用NdisMIndicateStatus通知所有的上层NDIS协议驱动程序.
其中: NDIS_STATUS_MEDIA_DISCONNECT 指示网线被拔掉,
NDIS_STATUS_MEDIA_CONNECT 指示网线被接上
NDIS_STATUS_LINK_SPEED_CHANGE 指示网卡速度改变,10/100自适应网卡才有。
网卡一般都有 status register 指示当然的连线状态,
也有网卡是通过获得 led status 来知道当前的连线状态的,
即绿灯亮表示连线,灭表示没有。
有些网卡拔掉或接上网线时会产生中断,在中断处理程序中一般也
检测网络连线状态并调用NdisMIndicateStatus,这样连线状态
在2000中就实时反应出来了,否则会在2秒钟内,即NDIS调用CheckForHangHandler后。这个功能是微软在PC97规范中定义的,所以ndis3没有这个功能。
linux对这个没有要求,novell netware对这个有要求,其它的操作系统我也不清楚。