Пример #1
0
        /// <summary>
        /// 同步发送消息给客户端
        /// </summary>
        /// <param name="target"></param>
        /// <param name="infomation"></param>
        public bool Send(ITcpClientProxy target, byte[] sendBuffer)
        {
            SocketAsyncEventArgs context = target.ReceiveContext;

            if (!IsSocketAlive(context))
            {
                return(false);
            }

            try
            {
                context.AcceptSocket.Send(sendBuffer);
                return(true);
            }
            catch (SocketException ex)
            {
                if (ex.ErrorCode == 10058)
                {
                    _logger.Error("客户端已断开。");
                }

                this.RecycleContext(context);
                return(false);
            }
            finally
            {
            }
        }
Пример #2
0
        /// <summary>
        /// 重用上次接收操作完毕的上下文对象来发送消息
        /// </summary>
        /// <param name="target"></param>
        /// <param name="sendBuffer"></param>
        public void SendReuseAsync(ITcpClientProxy target, byte[] sendBuffer)
        {
            byte[] cacheBuffer = new byte[_receiveBufferSize];
            Buffer.BlockCopy(sendBuffer, 0, cacheBuffer, 0, sendBuffer.Length);
            SocketAsyncEventArgs context = target.ReceiveContext;

            (target as ITcpClientProxy).PrepareOutgoingData(context, sendBuffer);
            StartSend(context);
        }
Пример #3
0
        /// <summary>
        /// 处理错误操作
        /// </summary>
        /// <param name="e"></param>
        private void ProcessError(SocketAsyncEventArgs e)
        {
            ITcpClientProxy handler = e.UserToken as ITcpClientProxy;

            if (!handler.IsDisposed)
            {
                lock (handler)
                {
                    if (handler.IsDisposed)
                    {
                        return;
                    }

                    Console.WriteLine("{0} 出错了,回收之。{1} : {2}",
                                      e.RemoteEndPoint,
                                      e.LastOperation,
                                      e.SocketError
                                      );
                    _logger.Error(string.Format("回收了一个客户端{0}。{1} : {2}",
                                                e.RemoteEndPoint,
                                                e.LastOperation,
                                                e.SocketError));

                    if (handler != null && handler.ClientStatus != (int)ClientStateEnums.Closed)
                    {
                        handler.ClientStatus = (int)ClientStateEnums.Closed;

                        // 通知外部事件
                        if (this.ClientDisconnected != null)
                        {
                            ClientStateEventArgs stateObject = new ClientStateEventArgs(e);
                            stateObject.ClientStatus = ClientStateEnums.Closed;

                            this.ClientDisconnected(this, stateObject);
                        }

                        this.RecycleContext(e);
                    }

                    handler.Dispose();
                }
            }
        }
Пример #4
0
        /// <summary>
        /// 处理发送操作
        /// 当一个发送操作完成时调用此方法
        /// </summary>
        /// <param name="context">与完成Send操作关联的SocketAsyncEventArg对象.</param>
        private void ProcessSend(SocketAsyncEventArgs context)
        {
            if (context.SocketError == SocketError.Success)
            {
                ITcpClientProxy token = context.UserToken as ITcpClientProxy;

                //todo: 长消息分段发
                //receiveSendToken.sendBytesRemainingCount = token.sendBytesRemainingCount - receiveSendEventArgs.BytesTransferred;


                // MSDN的例子
                //if (receiveSendToken.sendBytesRemainingCount == 0)
                //{
                //    // If we are within this if-statement, then all the bytes in
                //    // the message have been sent.
                //    StartReceive(receiveSendEventArgs);
                //}
                //else
                //{
                //    // If some of the bytes in the message have NOT been sent,
                //    // then we will need to post another send operation, after we store
                //    // a count of how many bytes that we sent in this send op.
                //    receiveSendToken.bytesSentAlreadyCount += receiveSendEventArgs.BytesTransferred;
                //    // So let's loop back to StartSend().
                //    StartSend(receiveSendEventArgs);
                //}


                // 调用发送事件
                this.OnMessageSend(context);


                // 读取客户端发送过来的下一段消息.
                StartReceive(context);
            }
            else
            {
                Console.WriteLine("Socket发送时错误,代号:" + context.SocketError);
                _logger.Error("Socket发送时错误,代号:" + context.SocketError);
                this.ProcessError(context);
            }
        }
Пример #5
0
        /// <summary>
        /// 处理接收操作
        /// 当一个异步接收操作完成时调用此方法
        /// </summary>
        /// <param name="receiveContext">与完成Receive操作关联的SocketAsyncEventArg对象</param>
        private void ProcessReceive(SocketAsyncEventArgs receiveContext)
        {
            if (!IsSocketAlive(receiveContext))
            {
                return;
            }

            // BytesTransferred属性提供在可接收或发送数据的异步套接字操作传输的字节数。
            // 如果从读取操作返回零,则说明远程端已关闭了连接
            if (receiveContext.BytesTransferred > 0)
            {
                if (receiveContext.SocketError == SocketError.Success)
                {
                    try
                    {
                        ITcpClientProxy dataHandler = receiveContext.UserToken as ITcpClientProxy;

                        //bool receiveComplete = dataHandler.ReceiveData(receiveContext);
                        List <IPackageInfo> packages = null;
                        bool receiveComplete         = dataHandler.TryReceivePackages(receiveContext, out packages);
                        if (receiveComplete)
                        {
                            // 调用消息接收完毕事件
                            try
                            {
                                this.OnMessageReceived(receiveContext);
                            }
                            catch (Exception ex)
                            {
                                _logger.Error(ex.StackTrace);
                            }

                            // 返回响应消息
                            // review: 这里应该用TryReceivePackages返回的集合?
                            IPackageInfo response = dataHandler.ExchangedData as IPackageInfo;
                            if (response != null)
                            {
                                SendReuseAsync(dataHandler, response.ToBytes());
                            }



                            else if (this.Echo)
                            {
                                SendReuseAsync(dataHandler, dataHandler.LastReceivedBytes);
                            }
                            else
                            {
                                StartReceive(receiveContext);
                            }

                            //string exchnagedData = dataHandler.ExchangedData == null ? "" : dataHandler.ExchangedData.ToString();
                            ////todo: 消息分段发送
                            //if (string.IsNullOrEmpty(exchnagedData) && this.Echo)
                            //{
                            //    //dataHandler.Echo(receiveContext);
                            //    //Send(dataHandler, dataHandler.LastMessage.Content);

                            //    if (packages.Count > 0)
                            //    {
                            //        Send(dataHandler, packages[0].ToBytes());
                            //    }

                            //    //Send(dataHandler, packages[0].ToBytes());
                            //}
                            //else
                            //{
                            //    //Send(dataHandler, exchnagedData);
                            //}

                            //dataHandler.PrepareOutgoingData(dataHandler.SendContext, exchnagedData);
                            //StartSend(dataHandler.SendContext);
                        }
                        else
                        {
                            // 如果没有读取完,继续接收下一段数据
                            StartReceive(receiveContext);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.Error("Unexpected error:" + ex.StackTrace);
                        Console.WriteLine("Unexpected error:" + ex.StackTrace);
                    }
                }
                else
                {
                    Console.WriteLine("Socket接受时错误, 代号:" + receiveContext.SocketError);
                    _logger.Error("Socket接受时错误, 代号:" + receiveContext.SocketError);

                    this.ProcessError(receiveContext);
                }
            }
            else
            {
                // 如果远程端关闭了连接,这里也关闭Socket
                Console.WriteLine("平板端关闭了连接.");
                _logger.Error("平板端关闭了连接.");
                this.ProcessError(receiveContext);
            }
        }
Пример #6
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
        }
Пример #7
0
        /// <summary>
        /// 异步发送消息给客户端
        /// </summary>
        /// <param name="target"></param>
        /// <param name="sendBuffer"></param>
        public void SendAsync(ITcpClientProxy target, byte[] sendBuffer)
        {
            //Byte[] sendBuffer = this._bufferEncoding.GetBytes(infomation);

            byte[] cacheBuffer = new byte[_receiveBufferSize];
            Buffer.BlockCopy(sendBuffer, 0, cacheBuffer, 0, sendBuffer.Length);

            // unused
            //SocketAsyncEventArgs context = this._sendPool.Pop();

            SocketAsyncEventArgs context = _poolOfReadWriteEventArgs.Pop();

            if (context == null)
            {
                context = new SocketAsyncEventArgs();
            }
            context.AcceptSocket = target.Connection;
            context.SetBuffer(cacheBuffer, 0, cacheBuffer.Length);
            context.UserToken = target;

            EventHandler <SocketAsyncEventArgs> processAsyncSend = null;

            processAsyncSend = new EventHandler <SocketAsyncEventArgs>(
                (sender, e) => {
                try
                {
                    #region 异步发送完毕处理

                    switch (e.LastOperation)
                    {
                    case SocketAsyncOperation.Send:
                        if (context.SocketError == SocketError.Success)
                        {
                            // 调用发送事件
                            this.OnMessageSend(context);
                        }
                        else
                        {
                            // 发送中出错,回收
                            context.Completed -= processAsyncSend;
                            this.ProcessError(context);
                            return;
                        }
                        break;
                    }

                    #endregion

                    // 如果已异步发送完毕,则回收
                    context.Completed   -= processAsyncSend;
                    context.AcceptSocket = null;
                    _poolOfReadWriteEventArgs.Push(context);
                }
                catch (Exception)
                {
                }
            });

            context.Completed += processAsyncSend;

            //if (!IsSocketAlive(context))
            //{
            //    ProcessError(context);
            //    return;
            //}

            (target as ITcpClientProxy).PrepareOutgoingData(context, sendBuffer);
            if (!IsSocketAlive(context))
            {
                return;
            }

            // 发送回客户端
            if (!context.AcceptSocket.SendAsync(context))
            {
                #region  步发送完毕

                processAsyncSend(this, context);

                #endregion
            }
        }
Пример #8
0
 public bool Send(ITcpClientProxy target, IPackageInfo content)
 {
     return(Send(target, content.ToBytes()));
 }