做了检测客户端在线的练习(用的是TCPListener和TCpClient)。我找到的例子都是必须先运行服务器再运行客户端,这样服务器才能检测到客户端是否在线。我想试试能不能不论先运行哪一方,当另一方运行后,服务器都可以检测到客户端是否在线。
    
    我的做法是这样的:1.在客户端我加了一个timer,定时去连接服务器    2.服务器将最新的一次连接记录下来。定时检查连接记录,如果连接记录的时间与当前时间相差超过了一定的范围,判断该客户端离线。
    
我想知道的问题是:1.我是不是又用了一个笨办法?如果是请给我指一条改进的路。    2.本来我想做的是让客户端定时发个心跳包给服务器的。但是我用的是TCPListener和TCpClient,如果只是定时去发个消息给服务器是不能让服务器检测到他在线的,必须定时让客户端去连接服务器,才能让服务器检测到他在线。在测试时发现,用我的这种检测客户端是否在线的方法在本机上是好的,如果把客户端放到了别的机子上,就不够稳定了,时好时坏。是我的代码的问题吗?

解决方案 »

  1.   

    server的代码:private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                Thread th = new Thread(StartServer);
                th.Start();
            }private void StartServer()
    {
        tlistener = new TcpListenerHelper(Dns.GetHostAddresses(Dns.GetHostName())[2].ToString(), 5555);
                tlistener.Start();
                tlistener.Listen();
                try
                {
                    while (tlistener.WaitForConnect())
                    {
                        string strMsg = tlistener.ReadMessage();
                        TreatPlayer(strMsg); //TreatPlayer用来处理客户端发给服务器的消息,收到<CONN>表示上线,服务器把这次连接信息记录下来用来定时比对以检测客户端是否在线,<GONE>表示离线
                        tlistener.Listen();
                    }
                }
                catch { }
            }服务器会定时检查在线列表,超过20秒没连接服务器的,判断为离线
      

  2.   

    client的代码_tC.Enabled = true;
    _tC.Interval = 5 * 1000;
     _tC.Tick += new EventHandler(_tC_Tick);void _tC_Tick(object sender, EventArgs e)
            {
                try
                {
                    Thread th = new Thread(StartClient);
                    th.Start();
                }
                catch { }
            } private void Form5_Load(object sender, EventArgs e)
            {
                Thread th = new Thread(StartClient);
                th.Start();
            }
    private void StartClient()
            {
                string serveraddress = "";
                StreamReader sr = new StreamReader(Application.StartupPath + @"\clientip.ini", Encoding.GetEncoding("utf-8"));
                string read = null;
                while ((read = sr.ReadLine()) != null)
                    serveraddress = read;
                sr.Close();
                
                try
                {
                    tclient = new TcpClientHelper(serveraddress, 5555);
                    tclient.Start();
                    tclient.SendMessage("<CONN>:" + Dns.GetHostAddresses(Dns.GetHostName())[2]);
                    string strMsg = "";
                    while (!string.IsNullOrEmpty(strMsg = tclient.ReadMessage()))
                    {
                        TreatRecv(strMsg, tclient);//处理服务器发来的消息
                    }
                }
                catch { }
            }
      

  3.   

    如果先运行客户端当然也可以,就如同你说的,让客户端定时尝试连接服务端,不过这个时间你可能需要把握好,太长了,有较长的延时,太短了又有性能的损耗.
    不妨考虑udp,可能会好点.
      

  4.   

    学习引用 1 楼 skep99 的回复:
    基本都这么实现的
    客户端和服务器实现长连接,再实现下丢包重发就完美了不好意思。“丢包重发”是什么意思?