/// <summary> /// 创建命令输入数据 /// </summary> /// <param name="buildInfo">TCP 客户端创建命令参数</param> /// <returns>下一个命令</returns> internal unsafe override TcpServer.ClientCommand.CommandBase Build(ref TcpServer.SenderBuildInfo buildInfo) { UnmanagedStream stream = Socket.OutputSerializer.Stream; if ((buildInfo.SendBufferSize - stream.ByteSize) >= sizeof(int)) { *(int *)stream.CurrentData = CommandInfo.Command | (int)(uint)(CommandInfo.CommandFlags | TcpServer.CommandFlags.NullData); stream.ByteSize += sizeof(int); return(LinkNext); } buildInfo.isFullSend = 1; return(this); }
/// <summary> /// 创建输出信息 /// </summary> /// <param name="sender">TCP 服务套接字数据发送</param> /// <param name="buildInfo">输出创建参数</param> internal unsafe override OutputLink Build(ServerSocketSenderBase sender, ref TcpServer.SenderBuildInfo buildInfo) { UnmanagedStream stream = sender.OutputSerializer.Stream; if ((buildInfo.SendBufferSize - stream.ByteSize) >= sizeof(int)) { OutputLink nextBuild = LinkNext; *(int *)stream.CurrentData = (byte)ReturnType; LinkNext = null; stream.ByteSize += sizeof(int); AutoCSer.Threading.RingPool <ReturnTypeOutput> .Default.PushNotNull(this); return(nextBuild); } buildInfo.isFullSend = 1; return(this); }
/// <summary> /// 创建输出信息 /// </summary> /// <param name="sender">TCP 服务套接字数据发送</param> /// <param name="buildInfo">输出创建参数</param> internal override OutputLink Build(TcpServer.ServerSocketSenderBase sender, ref TcpServer.SenderBuildInfo buildInfo) { UnmanagedStream stream = sender.OutputSerializer.Stream; if (stream.ByteSize == 0 || (buildInfo.SendBufferSize - stream.ByteSize) >= outputInfo.MaxDataSize) { ulong markData = sender.ServerSocket.MarkData; int streamLength = stream.ByteSize; OutputLink nextBuild = LinkNext; stream.PrepLength(sizeof(int) * 2); stream.ByteSize += sizeof(int); if (outputInfo.IsJsonSerialize == 0) { sender.Serialize(outputInfo, ref outputParameter); } else { sender.JsonSerialize(ref outputParameter); } int dataLength = stream.ByteSize - streamLength - sizeof(int); byte *dataStart = stream.Data.Byte + streamLength; *(int *)dataStart = dataLength + OutputDataSize; if (markData != 0) { TcpServer.CommandBase.Mark(dataStart + sizeof(int), markData, dataLength); } outputInfo.CheckMaxDataSize(Math.Max(dataLength + sizeof(int), stream.LastPrepSize - streamLength)); LinkNext = null; outputParameter = default(outputParameterType); AutoCSer.Threading.RingPool <Output <outputParameterType> > .Default.PushNotNull(this); return(nextBuild); } buildInfo.isFullSend = 1; return(this); }
/// <summary> /// 发送数据 /// </summary> internal unsafe void BuildOutput() { if (IsSocket) { TcpStreamServer.ServerOutput.OutputLink head = null, end; TcpServer.SenderBuildInfo buildInfo = new TcpServer.SenderBuildInfo { SendBufferSize = Server.SendBufferPool.Size, IsClientAwaiter = Server.Attribute.IsClientAwaiter }; UnmanagedStream outputStream; try { if (Buffer.Buffer == null) Server.SendBufferPool.Get(ref Buffer); if (OutputSerializer == null) outputStream = (OutputSerializer = BinarySerialize.Serializer.YieldPool.Default.Pop() ?? new BinarySerialize.Serializer()).SetTcpServer(); else outputStream = OutputSerializer.Stream; int outputSleep = OutputSleep, currentOutputSleep; do { buildInfo.IsNewBuffer = 0; fixed (byte* dataFixed = Buffer.Buffer) { byte* start = dataFixed + Buffer.StartIndex; STREAM: using (outputStream) { if (outputStream.Data.Byte != start) outputStream.Reset(start, Buffer.Length); buildInfo.Clear(); outputStream.ByteSize = 0; currentOutputSleep = outputSleep; if ((head = Outputs.GetClear(out end)) == null) goto CHECK; LOOP: do { head = head.Build(this, ref buildInfo); if (buildInfo.IsSend != 0 || !ServerSocket.IsVerifyMethod) { if (head != null) Outputs.PushHead(ref head, end); goto SEND; } } while (head != null); if (!Outputs.IsEmpty) { head = Outputs.GetClear(out end); goto LOOP; } CHECK: if (currentOutputSleep >= 0) { Thread.Sleep(currentOutputSleep); if (!Outputs.IsEmpty) { head = Outputs.GetClear(out end); currentOutputSleep = 0; goto LOOP; } } if (outputStream.ByteSize == 0) { outputStream.Dispose(); goto END; } SEND: buildInfo.IsNewBuffer = setSendData(start); } switch (send()) { case TcpOpenServer.SendState.Asynchronous: return; case TcpOpenServer.SendState.Error: buildInfo.IsError = true; return; } if (!Outputs.IsEmpty) { if (buildInfo.IsNewBuffer == 0) goto STREAM; goto FIXEDEND; } END: //IsOutput = 0; if (IsSocket) { Interlocked.Exchange(ref IsOutput, 0); if (!Outputs.IsEmpty) { if (Interlocked.CompareExchange(ref IsOutput, 1, 0) == 0) { if (buildInfo.IsNewBuffer == 0) goto STREAM; goto FIXEDEND; } } else if (!IsSocket && Interlocked.CompareExchange(ref IsOutput, 1, 0) == 0) buildInfo.IsClose = true; } else buildInfo.IsClose = true; return; FIXEDEND:; } } while (buildInfo.IsNewBuffer != 0); } catch (Exception error) { Server.Log.add(AutoCSer.Log.LogType.Error, error); buildInfo.IsError = true; } finally { if (buildInfo.IsError | buildInfo.IsClose) { if (buildInfo.IsError) closeSocket(); else close(); TcpStreamServer.ServerOutput.OutputLink.CancelLink(head); } } } else close(); }
/// <summary> /// 发送数据 /// </summary> internal unsafe void BuildOutput() { if (IsSocket) { TcpStreamServer.ServerOutput.OutputLink head = null, end; TcpServer.SenderBuildInfo buildInfo = new TcpServer.SenderBuildInfo { SendBufferSize = Server.SendBufferPool.Size, IsClientAwaiter = Server.Attribute.IsClientAwaiter }; UnmanagedStream outputStream; SocketError socketError; try { if (Buffer.Buffer == null) { Server.SendBufferPool.Get(ref Buffer); } if (OutputSerializer == null) { outputStream = (OutputSerializer = BinarySerialize.Serializer.YieldPool.Default.Pop() ?? new BinarySerialize.Serializer()).SetTcpServer(); } else { outputStream = OutputSerializer.Stream; } int outputSleep = OutputSleep, currentOutputSleep; do { buildInfo.IsNewBuffer = 0; fixed(byte *dataFixed = Buffer.Buffer) { byte *start = dataFixed + Buffer.StartIndex; currentOutputSleep = outputSleep; STREAM: using (outputStream) { RESET: if (outputStream.Data.Byte != start) { outputStream.Reset(start, Buffer.Length); } buildInfo.Clear(); outputStream.ByteSize = 0; if ((head = Outputs.GetClear(out end)) == null) { if (currentOutputSleep < 0) { goto CHECK; } Thread.Sleep(currentOutputSleep); if (Outputs.IsEmpty) { goto CHECK; } head = Outputs.GetClear(out end); currentOutputSleep = 0; } LOOP: do { head = head.Build(this, ref buildInfo); if (buildInfo.IsSend != 0 || !ServerSocket.IsVerifyMethod) { goto SETDATA; } }while (head != null); if (!Outputs.IsEmpty) { head = Outputs.GetClear(out end); goto LOOP; } if (!buildInfo.IsClientAwaiter) { if (currentOutputSleep >= 0) { Thread.Sleep(currentOutputSleep); if (!Outputs.IsEmpty) { head = Outputs.GetClear(out end); currentOutputSleep = 0; goto LOOP; } } } else { if (currentOutputSleep == int.MinValue) { currentOutputSleep = outputSleep; } if (currentOutputSleep >= 0) { Thread.Sleep(currentOutputSleep); } else { AutoCSer.Threading.ThreadYield.YieldOnly(); } if (!Outputs.IsEmpty) { head = Outputs.GetClear(out end); currentOutputSleep = 0; goto LOOP; } } CHECK: if (outputStream.ByteSize == 0) { goto DISPOSE; } SETDATA: buildInfo.IsNewBuffer = setSendData(start); SEND: if (IsSocket) { int sendSize = Socket.Send(sendData.Array, sendData.Start, sendData.Length, SocketFlags.None, out socketError); sendData.MoveStart(sendSize); if (sendData.Length == 0) { buildInfo.SendSizeLessCount = 0; if (buildInfo.IsNewBuffer == 0) { freeCopyBuffer(); if (head == null) { currentOutputSleep = int.MinValue; goto RESET; } if (outputStream.Data.Byte != start) { outputStream.Reset(start, Buffer.Length); } buildInfo.Clear(); outputStream.ByteSize = 0; //currentOutputSleep = outputSleep; goto LOOP; } CompressBuffer.TryFree(); if (head != null) { Outputs.PushHead(ref head, end); } //currentOutputSleep = outputSleep; goto DISPOSE; } if (socketError == SocketError.Success && (sendSize >= TcpServer.Server.MinSocketSize || (sendSize > 0 && buildInfo.SendSizeLessCount++ == 0))) { goto SEND; } buildInfo.IsError = true; } buildInfo.IsNewBuffer = 0; DISPOSE :; } if (buildInfo.IsNewBuffer == 0) { if (!buildInfo.IsError) { if (IsSocket) { //IsOutput = 0; Interlocked.Exchange(ref IsOutput, 0); if (!Outputs.IsEmpty) { if (Interlocked.CompareExchange(ref IsOutput, 1, 0) == 0) { goto STREAM; } } else if (!IsSocket && Interlocked.CompareExchange(ref IsOutput, 1, 0) == 0) { buildInfo.IsClose = true; } } else { buildInfo.IsClose = true; } } return; } } }while (buildInfo.IsNewBuffer != 0); } catch (Exception error) { Server.Log.add(AutoCSer.Log.LogType.Error, error); buildInfo.IsError = true; } finally { if (buildInfo.IsError | buildInfo.IsClose) { if (buildInfo.IsError) { closeSocket(); } else { close(); } TcpStreamServer.ServerOutput.OutputLink.CancelLink(head); } } } else { close(); } }