现在有个小需求,就是统计在线人数(winform),以前我用的方案是在数据库中增加一张表,如果登录则增加一条记录,如果登出,则删除一条记录,但是现在遇到一种情况,假如用户非法关机,那么这样统计出来的数据便不准确。在网上搜索了一下,说是利用socket中的poll方法可以实现这种需求,麻烦各位高手帮帮小弟,在线急等

解决方案 »

  1.   

    你思路问题 stock方式架构和现在架构完全不一样了
      

  2.   

    我以前没有用过socket,不知道怎么入手才好
      

  3.   

    Socket.Poll();确定Socket的状态。public bool Poll (
    int microSeconds,
    SelectMode mode
    )
      

  4.   

    KEEPALIVE 设置一下  然后捕获SOCKET异常 根据异常去判断用户是否关闭 
      

  5.   

    可以让客户端定期发送一个信号过来判断客户端是否在线,服务端可建立一个HashTable存储客户端状态,若长时间未连接则判断客户端离线.
      

  6.   

    楼主朋友,写代码呢,估计要写蛮多,一点点时间也不够,还是给你个理论吧,你可以自己去实践。要从服务端判断客户端是否掉线或SOCKET已关闭并不是非常难的事,首先先说下服务端判断客户端的SOCKET已关闭,这个问题可以通过服务端向客户端发送一条信息之后便可得到,其原理为:当客户端SOCKET已关闭后,服务端向其发送信息,那么服务端必将产生一个SOCKET异常代码为:10054(如果不是这个便是:10052)的异常代号,你只要捕获异常并判断其是否为上面给出的这个异常代码即可知道客户端是否关闭;如果要判断客户端是否掉线或客户端电脑是否因断电造成的非法关机的话,可以在客户端表列类中定义一个“上次收到数据的时间”时间类型变量,通过检测线程对其进行检测即可判断是否超时,其方法为将当前系统时间减掉“上次收到数据的时间”即可得出!上面写了这么多,不知道对楼主是否有帮助!
      

  7.   


    恩,谢谢你的分析,我试着写了两个程序,一个服务器端,一个客户端:
    客户端代码:        private int port = 80;//侦听端口号        private TcpClient tcpc;//对服务器创建TCP连接        private Socket socket;//发送套接字        private bool tcpConnect = false;//表示TCP连接是否成功        private void button1_Click(object sender, EventArgs e)
            {
                try
                {
                    //初始化一个socket实例
                    socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    //根据IP地址和端口号创建远程终结点
                    IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(textBox1.Text.Trim()), port);                //连接远程主机的8000端口号
                    EndPoint endPoint = (EndPoint)ipEndPoint;
                    socket.Connect(endPoint);
                    toolStripStatusLabel1.Text = "成功连接远程主机";
                    tcpConnect = true;
                    button1.Enabled = false;
                    button2.Enabled = true;
                }
                catch (Exception)
                {
                    toolStripStatusLabel1.Text = "目标计算机拒绝连接请求";
                }
            }        private void button2_Click(object sender, EventArgs e)
            {
                //获取要发送数据的长度
                int iLength = textBox2.Text.Length;            //根据获取的长度定义一个byte类型的数组
                Byte[] bySend = new byte[iLength];            //按照指定编码类型把字符串指定到指定的Byte数组
                bySend = System.Text.Encoding.Default.GetBytes(textBox2.Text);            int i = socket.Send(bySend);
                listBox1.Items.Add(textBox2.Text);
            }服务器端代码: //定义侦听端口号
            int port = 8000;
            //创建线程,用以侦听端口号,接收信息
            private Thread thThreadRead;
            //侦听端口号
            private TcpListener tlTcpListen;
            //设定标示位,判断侦听状态
            private bool blistener = true;
            private Socket stRead;       // private delegate void Listen();        private void button1_Click(object sender, EventArgs e)
            {
               // Listen lis = new Listen(listen);            thThreadRead = new Thread(new ThreadStart(listen));
                listen();
                //以Listen过程来初始化Thread实例
               thThreadRead.Start();
                //启动线程
                button1.Enabled = false;
            }        private void listen()
            {
                try
                {
                    //string ipAdress="127.0.0.1";
                    //Byte[] address = System.Text.Encoding.Default.GetBytes(ipAdress);
                    //IPAddress locaAddress = new IPAddress(address);
                    //以8000端口号来初始化TcpListener实例
                    tlTcpListen = new TcpListener(port);
                    //开始监听网络的连接请求
                    tlTcpListen.Start();
                    toolStripStatusLabel1.Text = "正在侦听...";
                    //通过连接请求,并获得接收数据时使用的Socket实例
                    stRead = tlTcpListen.AcceptSocket();
                    EndPoint tempRemoteEP = stRead.RemoteEndPoint;
                    IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;
                    //获取请求的远程计算机名称
                    IPHostEntry host = Dns.GetHostEntry(tempRemoteIP.Address);
                    string hostName = host.HostName;
                    toolStripStatusLabel1.Text = "已经连接";
                    //循环侦听
                    while (blistener)
                    {
                        //获取接收数据的时间
                        string sTime = DateTime.Now.ToShortTimeString();
                        Byte[] byRead = new byte[80];
                        //获得接收字节的数目
                        int iRead = stRead.ReceiveFrom(byRead, ref tempRemoteEP);
                        //并根据接收到的字节数目来定义字节数组
                        Byte[] byText = new Byte[iRead];
                        Array.Copy(byRead, 0, byText, 0, iRead);                    string sTemp = System.Text.Encoding.Default.GetString(byText);
                        if (sTemp.Trim() == "STOP")
                        {
                            stRead.Close();
                            tlTcpListen.Stop();
                            toolStripStatusLabel1.Text = "连接已关闭";
                            thThreadRead.Abort();
                            return;
                        }
                        else
                        {
                            listBox1.Items.Add(sTime + ":" + sTemp);
                        }
                    }
                }
                catch (System.Security.SecurityException)
                {
                    MessageBox.Show("侦听失败!", "错误");
                }
            }我测试了一下,客户端连接服务器端的时候,只要端口号正确都能连接上,但是到服务器端接收的时候,接收不到,麻烦看一下服务器端的代码是不是写的正确,由于我自己不会socket,是参考网上写出来的
      

  8.   

    Byte[] byRead = new byte[80];你服务这里定义缓冲区为80字节,但你客户端发送的却是根据文本框内的文本大小发送的,是否你服务端定义的缓冲区不够?你是一点都收不到,还是全部都收不到?
      

  9.   

    心跳问题啊,
    或者对每个socket都有单独的线程监控,socket正常/异常结束时都会通知server