private void Bind(Socket acceptSocket) { var exSocket = new TNSocket(acceptSocket); exSocket.LastAccessTime = DateTime.Now; var buffer = new byte[this.clientSettings.BufferSize * 2]; this.sendEventArg = new SocketAsyncEventArgs(); this.sendEventArg.SetBuffer(buffer, 0, this.clientSettings.BufferSize); var sendDataToken = new DataToken() { Socket = exSocket }; sendDataToken.bufferOffset = this.sendEventArg.Offset; this.sendEventArg.UserToken = sendDataToken; this.sendEventArg.AcceptSocket = acceptSocket; this.sendEventArg.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed); this.receiveEventArg = new SocketAsyncEventArgs(); this.receiveEventArg.SetBuffer(buffer, this.clientSettings.BufferSize, this.clientSettings.BufferSize); var receiveDataToken = new DataToken { Socket = exSocket, SyncSegments = new Queue <ArraySegment <byte> >() }; receiveDataToken.bufferOffset = this.receiveEventArg.Offset; this.receiveEventArg.UserToken = receiveDataToken; this.receiveEventArg.AcceptSocket = acceptSocket; this.receiveEventArg.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed); if (IsSyncReceived) { DataReceived += OnReceived; } requestHandler.Bind(this); }
private void TryDequeueAndPostSend(TNSocket socket, SocketAsyncEventArgs ioEventArgs) { SocketAsyncResult result; if (socket.TryDequeueOrReset(out result)) { DataToken dataToken = (DataToken)ioEventArgs.UserToken; dataToken.Socket = socket; dataToken.AsyncResult = result; dataToken.byteArrayForMessage = result.Data; dataToken.messageLength = result.Data.Length; try { PostSend(ioEventArgs); } catch (Exception ex) { dataToken.ResultCallback(ResultCode.Error, ex); ResetSendFlag(); } } else { //ResetSendFlag(); } }
/// <summary> /// /// </summary> /// <param name="exSocket"></param> /// <param name="opCode"></param> /// <param name="reason"></param> protected void Dispose(TNSocket exSocket, sbyte opCode, string reason) { try { var e = new SocketEventArgs() { Socket = exSocket, Source = new DataMessage() { OpCode = opCode, Message = reason } }; DoClosed(e); OnDisconnected(e); if (exSocket != null) { exSocket.Close(); } sendEventArg.Dispose(); receiveEventArg.Dispose(); receiveWaitEvent.Dispose(); socketClient.Dispose(); } catch (Exception ex) { TraceLog.WriteError("Dispose connect of client error:{0}", ex); } }
/// <summary> /// /// </summary> /// <param name="exSocket"></param> /// <param name="opCode"></param> /// <param name="data"></param> /// <param name="offset"></param> /// <param name="count"></param> /// <returns></returns> public override byte[] BuildMessagePack(TNSocket exSocket, sbyte opCode, byte[] data, int offset, int count) { byte[] buffer = new byte[count + 4]; Buffer.BlockCopy(BitConverter.GetBytes(count), 0, buffer, 0, 4); Buffer.BlockCopy(data, offset, buffer, 4, count); return(buffer);//buffer; }
private void DoClosedStatus(TNSocket socket, int statusCode) { Action <TNSocket, int> handler = OnClosedStatus; if (handler != null) { handler(socket, statusCode); } }
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="opCode"></param> /// <param name="reason"></param> public virtual void SendCloseHandshake(TNSocket socket, sbyte opCode, string reason) { if (MessageProcessor != null) { byte[] data = MessageProcessor.CloseMessage(socket, opCode, reason); if (data != null) { AppServer.SendAsync(socket, data, result => { }); } } }
private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs) { try { Interlocked.Increment(ref _summaryStatus.TotalConnectCount); maxConnectionsEnforcer.WaitOne(); if (acceptEventArgs.SocketError != SocketError.Success) { Interlocked.Increment(ref _summaryStatus.RejectedConnectCount); HandleBadAccept(acceptEventArgs); } else { Interlocked.Increment(ref _summaryStatus.CurrentConnectCount); SocketAsyncEventArgs ioEventArgs = this.ioEventArgsPool.Pop(); ioEventArgs.AcceptSocket = acceptEventArgs.AcceptSocket; var dataToken = (DataToken)ioEventArgs.UserToken; ioEventArgs.SetBuffer(dataToken.bufferOffset, socketSettings.BufferSize); var exSocket = new TNSocket(ioEventArgs.AcceptSocket); exSocket.LastAccessTime = DateTime.Now; dataToken.Socket = exSocket; acceptEventArgs.AcceptSocket = null; //release connect when socket has be closed. ReleaseAccept(acceptEventArgs, false); try { OnConnected(new ConnectionEventArgs { Socket = exSocket }); } catch (Exception ex) { TraceLog.WriteError("OnConnected error:{0}", ex); } PostReceive(ioEventArgs); } } finally { PostAccept(); } }
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="buffer"></param> /// <param name="callback"></param> internal protected override async Task <bool> SendAsync(TNSocket socket, byte[] buffer, Action <SocketAsyncResult> callback) { //socket.Enqueue(buffer, callback); if (socket.DirectSendOrEnqueue(buffer, callback)) { try { TryDequeueAndPostSend(socket, sendEventArg); return(true); } catch (Exception ex) { ResetSendFlag(); TraceLog.WriteError("SendAsync {0} error:{1}", socket.RemoteEndPoint, ex); } } return(false); }
private void TryDequeueAndPostSend(TNSocket socket, SocketAsyncEventArgs ioEventArgs) { bool isOwner = ioEventArgs == null; SocketAsyncResult result; if (socket.TryDequeueOrReset(out result)) { if (ioEventArgs == null) { ioEventArgs = ioEventArgsPool.Pop(); ioEventArgs.AcceptSocket = socket.WorkSocket; } DataToken dataToken = (DataToken)ioEventArgs.UserToken; dataToken.Socket = socket; dataToken.AsyncResult = result; dataToken.byteArrayForMessage = result.Data; dataToken.messageLength = result.Data.Length; try { PostSend(ioEventArgs); } catch (Exception ex) { dataToken.ResultCallback(ResultCode.Error, ex); if (isOwner) { ReleaseIOEventArgs(ioEventArgs); } socket.ResetSendFlag(); } } else { ReleaseIOEventArgs(ioEventArgs); //socket.ResetSendFlag(); } }
/// <summary> /// Posts the send. /// </summary> /// <param name="socket"></param> /// <param name="opCode"></param> /// <param name="data">Data.</param> /// <param name="offset">Offset.</param> /// <param name="count">Count.</param> /// <param name="callback"></param> public override async Task PostSend(TNSocket socket, sbyte opCode, byte[] data, int offset, int count, Action <SocketAsyncResult> callback) { byte[] buffer = requestHandler.MessageProcessor.BuildMessagePack(socket, opCode, data, offset, count); await SendAsync(socket, buffer, callback); }
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="opCode"></param> /// <param name="data"></param> /// <param name="offset"></param> /// <param name="count"></param> public override async Task PostSend(TNSocket socket, sbyte opCode, byte[] data, int offset, int count) { await PostSend(socket, opCode, data, offset, count, result => { }); }
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="data"></param> /// <param name="offset"></param> /// <param name="count"></param> public override async Task PostSend(TNSocket socket, byte[] data, int offset, int count) { await PostSend(socket, OpCode.Binary, data, offset, count); }
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="opCode"></param> /// <param name="data"></param> /// <param name="offset"></param> /// <param name="count"></param> /// <param name="callback"></param> public abstract Task PostSend(TNSocket socket, sbyte opCode, byte[] data, int offset, int count, Action <SocketAsyncResult> callback);
/// <summary> /// /// </summary> /// <param name="socket"></param> public abstract void Pong(TNSocket socket);
/// <summary> /// /// </summary> /// <param name="exSocket"></param> /// <param name="opCode"></param> /// <param name="reason"></param> public override byte[] CloseMessage(TNSocket exSocket, sbyte opCode, string reason) { return(null); }
/// <summary> /// /// </summary> /// <param name="exSocket"></param> /// <param name="opCode"></param> /// <param name="data"></param> /// <param name="offset"></param> /// <param name="count"></param> /// <returns></returns> public abstract byte[] BuildMessagePack(TNSocket exSocket, sbyte opCode, byte[] data, int offset, int count);
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="buffer"></param> /// <param name="callback"></param> public void SendMessage(TNSocket socket, byte[] buffer, Action <SocketAsyncResult> callback) { AppServer.SendAsync(socket, buffer, callback); }
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="opCode"></param> /// <param name="data"></param> /// <param name="offset"></param> /// <param name="count"></param> public abstract Task PostSend(TNSocket socket, sbyte opCode, byte[] data, int offset, int count);
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="reason"></param> public override void CloseHandshake(TNSocket socket, string reason) { requestHandler.SendCloseHandshake(socket, OpCode.Close, reason); }
/// <summary> /// 处理数据接收回调 /// </summary> /// <param name="ioEventArgs"></param> private void ProcessReceive(SocketAsyncEventArgs ioEventArgs) { DataToken dataToken = (DataToken)ioEventArgs.UserToken; if (ioEventArgs.BytesTransferred == 0) { //对方主动关闭socket //if (logger.IsDebugEnabled) logger.Debug("对方关闭Socket"); Closing(ioEventArgs, OpCode.Empty); return; } if (ioEventArgs.SocketError != SocketError.Success) {//Socket错误 TraceLog.Write("ProcessReceive IP {0} SocketError:{1}, bytes len:{2}", (dataToken != null ? dataToken.Socket.RemoteEndPoint.ToNotNullString() : ""), ioEventArgs.SocketError.ToString(), ioEventArgs.BytesTransferred); Closing(ioEventArgs); return; } TNSocket exSocket = dataToken == null ? null : dataToken.Socket; List <DataMessage> messages; bool hasHandshaked; bool needPostAnother = requestHandler.TryReceiveMessage(ioEventArgs, out messages, out hasHandshaked); if (hasHandshaked) { OnHandshaked(new ConnectionEventArgs { Socket = exSocket }); } //modify reason:数据包接收事件触发乱序 if (messages != null) { foreach (var message in messages) { try { switch (message.OpCode) { case OpCode.Close: var statusCode = requestHandler.MessageProcessor != null ? requestHandler.MessageProcessor.GetCloseStatus(message.Data) : OpCode.Empty; if (statusCode != OpCode.Empty) { DoClosedStatus(exSocket, statusCode); } Closing(ioEventArgs, OpCode.Empty); needPostAnother = false; break; case OpCode.Ping: DoPing(new ConnectionEventArgs { Socket = exSocket, Message = message }); break; case OpCode.Pong: DoPong(new ConnectionEventArgs { Socket = exSocket, Message = message }); break; default: OnDataReceived(new ConnectionEventArgs { Socket = exSocket, Message = message }); break; } } catch (Exception ex) { TraceLog.WriteError("OnDataReceived error:{0}", ex); } } } if (needPostAnother) { PostReceive(ioEventArgs); //是否需要关闭连接 if (exSocket.IsClosed) { ResetSAEAObject(ioEventArgs); } } }
/// <summary> /// /// </summary> /// <param name="socket"></param> public override void Pong(TNSocket socket) { byte[] data = Encoding.UTF8.GetBytes("pong"); PostSend(socket, OpCode.Pong, data, 0, data.Length); }
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="reason"></param> public abstract void CloseHandshake(TNSocket socket, string reason);
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="reason"></param> public override void CloseHandshake(TNSocket socket, string reason) { Dispose(socket, OpCode.Close, reason); }
/// <summary> /// /// </summary> /// <param name="exSocket"></param> /// <param name="opCode"></param> /// <param name="reason"></param> public abstract byte[] CloseMessage(TNSocket exSocket, sbyte opCode, string reason);
/// <summary> /// /// </summary> /// <param name="socket"></param> /// <param name="message"></param> /// <param name="encoding"></param> /// <param name="callback"></param> public void SendMessage(TNSocket socket, string message, Encoding encoding, Action <SocketAsyncResult> callback) { byte[] buffer = encoding.GetBytes(message); SendMessage(socket, buffer, callback); }
/// <summary> /// not proccess buildpack /// </summary> /// <param name="socket"></param> /// <param name="buffer"></param> /// <param name="callback"></param> protected internal abstract Task <bool> SendAsync(TNSocket socket, byte[] buffer, Action <SocketAsyncResult> callback);