예제 #1
0
 /// <summary>
 /// 异步接收操作完成时调用此方法
 /// 如果远程主机关闭了连接,则该套接字被关闭
 /// 如果接收到数据,则数据将回传给客户端
 /// </summary>
 /// <param name="e"></param>
 private void ProcessReceive(SocketAsyncEventArgs e)
 {
     try
     {
         // 检查如果客户端关闭连接
         AsyncUserToken token = (AsyncUserToken)e.UserToken;                 // 获取用户信息
         if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) // 如果字节存在
         {
             Byte[] data = new Byte[e.BytesTransferred];                     // 从套接字中获取数据
             Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred);
             lock (token.Buffer)
             {
                 token.Buffer.AddRange(data);// 锁定接收数据
             }
             //注意:你一定会问,这里为什么要用do-while循环?
             //如果当客户发送大数据流的时候,e.BytesTransferred的大小就会比客户端发送过来的要小,
             //需要分多次接收.所以收到包的时候,先判断包头的大小.够一个完整的包再处理.
             //如果客户短时间内发送多个小数据包时, 服务器可能会一次性把他们全收了.
             //这样如果没有一个循环来控制,那么只会处理第一个包,
             //剩下的包全部留在token.Buffer中了,只有等下一个数据包过来后,才会放出一个来.
             do
             {
                 byte[] lenBytes   = token.Buffer.GetRange(0, 4).ToArray(); // 获取头说明
                 int    packageLen = BitConverter.ToInt32(lenBytes, 0);     // 获取包长度
                 if (packageLen > token.Buffer.Count - 4)
                 {
                     break;                                                   // 长度不够时,退出循环,让程序继续接收
                 }
                 byte[] rev = token.Buffer.GetRange(4, packageLen).ToArray(); // 包够长时,则提取出来,交给后面的程序去处理
                 lock (token.Buffer)
                 {
                     token.Buffer.RemoveRange(0, packageLen + 4); // 锁定线程并从数据池中移除这组数据
                 }
                 ReceiveClientData?.Invoke(token, rev);           // 将数据包交给后台处理,这里你也可以新开个线程来处理.加快速度
                 //string msg = Encoding.UTF8.GetString(rev);
                 //server.lbxInfo.Items.Add(msg);// 输出信息
                 //这里API处理完后,并没有返回结果,当然结果是要返回的,却不是在这里, 这里的代码只管接收.
                 //若要返回结果,可在API处理中调用此类对象的SendMessage方法,统一打包发送.不要被微软的示例给迷惑了.
             } while (token.Buffer.Count > 4);
             //继续接收. 为什么要这么写,请看Socket.ReceiveAsync方法的说明
             if (!token.Socket.ReceiveAsync(e))
             {
                 this.ProcessReceive(e);
             }
         }
         else
         {
             CloseClientSocket(e);
         }
     }
     catch (Exception ex)
     {
         AsyncUserToken token = e.UserToken as AsyncUserToken;
         log.AddLog(LogType.Error, $"异步接收数据操作时出错!\r\n客户端地址:{token.IPAddress}\r\n错误信息:{ex.Message}");
     }
 }
예제 #2
0
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            try
            {
                // check if the remote host closed the connection
                UserToken token = (UserToken)e.UserToken;
                if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
                {
                    //读取数据
                    byte[] data = new byte[e.BytesTransferred];
                    Array.Copy(e.Buffer, e.Offset, data, 0, e.BytesTransferred);
                    lock (token.Buffer)
                    {
                        token.Buffer.AddRange(data);
                    }
                    do
                    {
                        //判断包的长度
                        byte[] lenBytes   = token.Buffer.GetRange(0, 4).ToArray();
                        int    packageLen = BitConverter.ToInt32(lenBytes, 0);
                        if (packageLen > token.Buffer.Count - 4)
                        {   //长度不够时,退出循环,让程序继续接收
                            break;
                        }

                        //包够长时,则提取出来,交给后面的程序去处理
                        byte[] rev = token.Buffer.GetRange(4, packageLen).ToArray();
                        //从数据池中移除这组数据
                        lock (token.Buffer)
                        {
                            token.Buffer.RemoveRange(0, packageLen + 4);
                        }
                        ReceiveClientData?.Invoke(token, rev);
                    } while (token.Buffer.Count > 4);
                    if (!token.Socket.ReceiveAsync(e))
                    {
                        this.ProcessReceive(e);
                    }
                }
                else
                {
                    //CloseClientSocket(e);
                }
            }
            catch (Exception xe)
            {
                Console.WriteLine(xe.Message + "\r\n" + xe.StackTrace);
            }
        }
예제 #3
0
        /// <summary>
        /// 开始侦听客户端连接
        /// </summary>
        /// <returns></returns>
        public static bool Start(ReceiveClientData tmp_rcdataHandler)
        {
            rcdataHandler = tmp_rcdataHandler;
            bRunning      = true;
            bool bRet = false;

            if (myListener == null)
            {
                try
                {
                    System.Net.IPAddress localaddr = System.Net.IPAddress.Any; //设定服务器默认IP地址

                    //开始监听
                    myListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    myListener.Bind((EndPoint)(new IPEndPoint(localaddr, LogInfo.Constant.ClientListenPort)));
                    myListener.Listen(100);

                    myListener_other = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    myListener_other.Bind(new IPEndPoint(localaddr, LogInfo.Constant.ClientOtherListenPort));
                    myListener_other.Listen(10);

                    myListener_news = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    myListener_news.Bind(new IPEndPoint(localaddr, LogInfo.Constant.ClientNewsListenPort));
                    myListener_news.Listen(10);

                    thread = new Thread(StartListen);
                    thread.Start();
                    thread_other = new Thread(StartListen_Other);
                    thread_other.Start();
                    thread_news = new Thread(StartListen_News);
                    thread_news.Start();

                    LogInfo.Log.WriteInfo(LogInfo.LogType.Info, "开始监听客户端。\r\n");
                    bRet = true;
                }
                catch (Exception ee)
                {
                    LogInfo.Log.WriteInfo(LogInfo.LogType.Error, "开始监听客户端错误:" + ee.ToString() + "\r\n");
                    MessageBox.Show("请检查网络连接状态!", "错误");
                }
            }

            if (!bRet)
            {
                bRunning = false;
            }
            return(bRet);
        }