/// <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 { } }
/// <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); }
/// <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(); } } }
/// <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); } }
/// <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); } }
/// <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 }
/// <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 } }
public bool Send(ITcpClientProxy target, IPackageInfo content) { return(Send(target, content.ToBytes())); }