如何判断远程主机是否在线

wddpxqq 2009-12-22 04:59:07
现在要做一个服务器端,当用户上线的时候,发消息给服务器,服务器知道客户端上线了,当用户下线的时候再发个消息,服务器就更新客户端的状态,但是当客户端异常短线的时候,这时服务器端就没办法知道用户是否在线了,如果给用户发了消息后,他不在,就可能将消息丢失,现在就是想做一个判断,就像用ping那样,如果ping不通,那么我就将消息缓存,等待客户端上线后发给他
现在的问题就是在C#中,这个类似Ping的命令,要怎么来写这个方法呢?
请各位大虾救命
...全文
575 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
fuhaohua 2010-01-04
  • 打赏
  • 举报
回复
路过。。。。
lizhigang34 2009-12-23
  • 打赏
  • 举报
回复
下面是PING代码,来源code project网站

//------------------------------------------------------------------------------------------------------------------
//icmpecho.h
//------------------------------------------------------------------------------------------------------------------

#include <afxsock.h>
#pragma comment(lib, "Iphlpapi.lib")

class CIcmpEcho : public CSocket
{
// Attributes
public:

// Operations
public:
CIcmpEcho();
virtual ~CIcmpEcho();

unsigned long ResolveIP(CString strIP);
unsigned long ResolveName(CString strHostName);

DWORD PingHost(unsigned long ulIP, int iPingTimeout);

CString GetIP(unsigned long ulIP);

// Overrides
public:
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CIcmpEcho)
//}}AFX_VIRTUAL

// Generated message map functions
//{{AFX_MSG(CIcmpEcho)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG

// Implementation
protected:
};
/////////////////////////////////////////////////////////////////////////////



//------------------------------------------------------------------------------------------------------------------
//icmpecho.cpp
//------------------------------------------------------------------------------------------------------------------

// IcmpEcho.cpp : implementation file
//

#include "CIcmpEcho.h"

extern "C" {
#include "ipexport.h"
#include "icmpapi.h"
}

#define PING_TIMEOUT 100

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CIcmpEcho

CIcmpEcho::CIcmpEcho()
{
}

CIcmpEcho::~CIcmpEcho()
{
}


// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CIcmpEcho, CSocket)
//{{AFX_MSG_MAP(CIcmpEcho)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0

/////////////////////////////////////////////////////////////////////////////
// CIcmpEcho member functions
unsigned long CIcmpEcho::ResolveIP(CString strIP)
{
//Task 1: Given IP Address i.e. "111.111.111.111",
// Return Network byte ordered address (ulIP)

unsigned long ulIP;

ulIP =(IPAddr)inet_addr(strIP);

return ulIP;
}

unsigned long CIcmpEcho::ResolveName(CString strHostName)
{
//Task 1: Resolve HostName (through DNS or WINS, whichever appropriate)
//Task 2: Return network byte ordered address (ulIP)

unsigned long ulIP;
hostent* phostent;

phostent = gethostbyname(strHostName);

if (phostent == NULL)
return 0;

ulIP = *(DWORD*)(*phostent->h_addr_list);

return ulIP;

}

DWORD CIcmpEcho::PingHost(unsigned long ulIP, int iPingTimeout)
{
//Task 1: Open ICMP Handle
//Task 2: Create Structure to receive ping reply
//Task 3: SendPing (SendEcho)
//Task 4: Close ICMP Handle
//Task 5: Return RoundTripTime

unsigned long ip = ulIP;

HANDLE icmphandle = IcmpCreateFile();

char reply[sizeof(icmp_echo_reply)+8];

icmp_echo_reply* iep=(icmp_echo_reply*)&reply;
iep->RoundTripTime = 0xffffffff;

IcmpSendEcho(icmphandle,ip,0,0,NULL,reply,sizeof(icmp_echo_reply)+8,iPingTimeout);

IcmpCloseHandle(icmphandle);

return iep->RoundTripTime;

}

CString CIcmpEcho::GetIP(unsigned long ulIP)
{
//Task 1: Given a host order ulIP Address
// Return a IP address in format of xxx.xxx.xxx.xxx

LPSTR szAddr;

struct in_addr inetAddr;

inetAddr.s_addr = (IPAddr)ulIP;

szAddr = inet_ntoa(inetAddr);

CString csIP = szAddr;

return csIP;

}

///////////////////
//使用部分

CIcmpEcho icmp;
unsigned long lIP = icmp.ResolveIP("192.168.1.1");
DWORD dw = icmp.PingHost(lIP, 1000);
ziplj 2009-12-23
  • 打赏
  • 举报
回复
心跳包就是客户端每隔一段时间(比如一分钟)发送一点数据给服务器 告诉服务器说 我还活着 你不要抛弃我
如果客户端死掉了 一分钟以后服务器没收到心跳包 就说么他死掉了 就可以抛弃他了
至于发送什么数据 自己随便定 原则上是很短的一个小数据包 减少服务器的压力


TCP链接仍然建议使用心跳
wddpxqq 2009-12-23
  • 打赏
  • 举报
回复
我用的是UDP的协议。我现在关键是,想知道如何来写这个代码啊!recv函数是那个类库里的呢?
wddpxqq 2009-12-23
  • 打赏
  • 举报
回复
结贴散分
wddpxqq 2009-12-23
  • 打赏
  • 举报
回复
ex.ErrorCode==10060
这个错误代码是远程主机无响应时返回的
wddpxqq 2009-12-23
  • 打赏
  • 举报
回复
我自己的做法是:看代码

try
{
socket.Connect(iep);
socket.Shutdown(SocketShutdown.Both);
socket.Close();
return true;
}
catch ( SocketException ex)
{
//目标主机无应答时
if (ex.ErrorCode==10060)
{
socket.Close();
return false;
}
return true;

}


这个也能实现查看到远程主机是否连接的问题吧!
sigma_ 2009-12-22
  • 打赏
  • 举报
回复
如果是udp方式,需要用心跳包。如果是TCP方式,用不用心跳都可以,可以根据recv函数的返回值和抛出的异常来判断。

这种方式可行
tsj2209 2009-12-22
  • 打赏
  • 举报
回复
mark
Apple_Demo 2009-12-22
  • 打赏
  • 举报
回复
根据recv函数的返回值来判断。
zyq5945 2009-12-22
  • 打赏
  • 举报
回复
QQ客户端每隔一分钟左右发UDP心跳给服务器
西贝山人 2009-12-22
  • 打赏
  • 举报
回复
发送信息如果没有接受返回的数据,就认为客户端没在线或没空接受,就保存信息然后一直发,直到客户端接收到为止。
西贝山人 2009-12-22
  • 打赏
  • 举报
回复
一直发送知道客户端接收到返回为止,不知道可不可以。QQ是不是这样的啊?
jackson35296 2009-12-22
  • 打赏
  • 举报
回复
如果是udp方式,需要用心跳包。如果是TCP方式,用不用心跳都可以,可以根据recv函数的返回值和抛出的异常来判断。
wddpxqq 2009-12-22
  • 打赏
  • 举报
回复
怎么个心跳法啊!给我段代码研究哈
sandyandy 2009-12-22
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 ziplj 的回复:]
发送心跳包  根据心跳包是否超时来判断用户是否在线 
[/Quote]

YES
danxuezx 2009-12-22
  • 打赏
  • 举报
回复
c#不会用,c++的ping代码我倒是有,我想可以把它封装在dll里然后在c#中调用
百事烟 2009-12-22
  • 打赏
  • 举报
回复
服务器给客户发消息采用应答机制,一问一答
ziplj 2009-12-22
  • 打赏
  • 举报
回复
发送心跳包 根据心跳包是否超时来判断用户是否在线

18,356

社区成员

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

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