Пример #1
0
        /// <summary>
        /// 处理连接请求
        /// </summary>
        /// <param name="acceptContext">与完成Accept操作关联的SocketAsyncEventArg对象</param>
        private void ProcessAccept(SocketAsyncEventArgs acceptContext)
        {
            // 1.新的连接
            Socket acceptSocket = acceptContext.AcceptSocket;

            if (acceptSocket != null && acceptContext.SocketError == SocketError.Success)
            {
                try
                {
                    // 从对象池中取出一个用于读取的SocketAsyncEventArgs对象,将连接到的Socket客户端放入UserToken
                    SocketAsyncEventArgs readEventArgs = _poolOfReadWriteEventArgs.Pop();
                    if (readEventArgs == null)
                    {
                        Trace.WriteLine(string.Format("连接数已满,拒绝 {0} 的连接请求。", acceptSocket.RemoteEndPoint));
                        acceptSocket.Close();
                        return;
                    }

                    readEventArgs.Completed += SocketAsyncEventArgs_IOCompleted;


                    ITcpClientProxy clientHandler = null;

                    #region 处理连接信息

                    if (CreateClientHandler != null)
                    {
                        clientHandler = CreateClientHandler(acceptSocket, Setting);
                        clientHandler.FeedbackTime   = DateTime.Now;
                        clientHandler.ReceiveContext = readEventArgs;
                        clientHandler.ClientStatus   = (int)ClientStateEnums.Connected;
                    }

                    #endregion

                    //将连接SAEA侦听到的Socket传递给用于收发的SAEA
                    readEventArgs.AcceptSocket = acceptSocket;
                    readEventArgs.UserToken    = clientHandler;

                    // 增加连接数
                    if (clientHandler != null)
                    {
                        _clientMembers.Add(clientHandler);
                    }

                    _logger.Info(string.Format("{0} {1}连接上教师机, 目前服务器上有{2}个连接。",
                                               DateTime.Now.ToString("HH:mm:ss"),
                                               acceptSocket.RemoteEndPoint,
                                               this.ConnectedCount));

                    // 通知外部,有新的连接
                    OnClientConnected(readEventArgs);

                    // 开始侦听该连接传入的数据
                    this.StartReceive(readEventArgs);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("连接时发生错误:" + ex.StackTrace);
                    _logger.Error("接收连接时错误:" + ex.StackTrace);
                }
            }
            else
            {
                //Close方法关闭并释放所有资源(托管和非托管), 内部调用了Dispose
                if (acceptSocket != null)
                {
                    acceptSocket.Close();
                }
                _semaphoreAcceptedClients.Release();
            }


            #region 最后的处理,接收下个连接

            // 开始接收新的连接(而不是立即重用当前的acceptContext,以提升性能)
            this.StartAccept();

            // 将SAEA对象放回连接池,以便重用
            acceptContext.Completed   -= this.SocketAsyncEventArgs_IOCompleted;
            acceptContext.AcceptSocket = null; // 2015-05-20
            _poolOfAcceptEventArgs.Push(acceptContext);

            #endregion
        }
Пример #2
0
        /// <summary>
        /// 停止侦听服务.
        /// </summary>
        public void Stop()
        {
            _logger.Info("主动关闭TCP, 断开接连。");


            // 先通知所有客户端断开
            if (_clientMembers != null)
            {
                for (int index = _clientMembers.Count - 1; index >= 0; index--)
                {
                    var clientHandler = _clientMembers[index];

                    try
                    {
                        if (this.ClientDisconnected != null)
                        {
                            ClientStateEventArgs stateObject = new ClientStateEventArgs(clientHandler.ReceiveContext);
                            stateObject.ClientStatus = ClientStateEnums.Closed;

                            this.ClientDisconnected(this, stateObject);
                        }

                        //_clientHandlers.Remove(clientHandler);
                    }
                    catch (Exception ex)
                    {
                        // 外部未处理的异常,记录日志,不影响主流程。
                        _logger.Error(ex.StackTrace);
                    }

                    //this.RecycleContext(clientHandler.ReceiveContext);
                }
            }

            lock (_tcpLock)
            {
                // 1.pulse thread close
                this.StopCheckingPulse();

                // 清理缓存,事件
                SocketAsyncEventArgs eventArgs;
                while (this._poolOfAcceptEventArgs.Count > 0)
                {
                    eventArgs            = _poolOfAcceptEventArgs.Pop();
                    eventArgs.Completed -= SocketAsyncEventArgs_IOCompleted;
                    //_bufferManager.FreeBuffer(eventArgs);
                    eventArgs.Dispose();
                }
                while (this._poolOfReadWriteEventArgs.Count > 0)
                {
                    eventArgs            = _poolOfReadWriteEventArgs.Pop();
                    eventArgs.Completed -= SocketAsyncEventArgs_IOCompleted;
                    _bufferManager.FreeBuffer(eventArgs);
                    eventArgs.Dispose();
                }


                _bufferManager = null;
                //GC.Collect();

                try
                {
                    //_socketListener.Disconnect(true);
                    //_socketListener.Shutdown(SocketShutdown.Both);
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.StackTrace);
                }
                finally
                {
                    if (_socketListener != null)
                    {
                        _socketListener.Close();
                        _socketListener.Dispose();
                        _socketListener = null;
                    }
                }

                mutex.ReleaseMutex();
                this._semaphoreAcceptedClients.Release();


                // 清掉当前客户端
                foreach (var client in _clientMembers)
                {
                    Socket s = client.Connection;
                    try
                    {
                        s.Close();
                        //s.Shutdown(SocketShutdown.Receive);
                        //s.Disconnect(true);
                    }
                    catch (Exception)
                    {
                    }
                    finally
                    {
                        if (s.Connected)
                        {
                            s.Close();
                            s.Dispose();
                        }
                        s = null;
                    }
                }
                _clientMembers.Clear();
            }
        }