/// <summary> /// 发送数据 /// </summary> internal unsafe void BuildOutput() { if (IsSocket) { TcpServer.ServerOutput.OutputLink head = null, end; TcpServer.SenderBuildInfo buildInfo = new TcpServer.SenderBuildInfo { SendBufferSize = Server.SendBufferPool.Size }; UnmanagedStream outputStream; SocketError socketError; try { if (Buffer.Buffer == null) { Server.SendBufferPool.Get(ref Buffer); } if (OutputSerializer == null) { outputStream = (OutputSerializer = BinarySerializer.YieldPool.Default.Pop() ?? new BinarySerializer()).SetTcpServer(); } else { outputStream = OutputSerializer.Stream; } TcpServer.OutputWaitType outputWaitType = Server.ServerAttribute.OutputWaitType, currentOutputWaitType; do { buildInfo.IsNewBuffer = 0; fixed(byte *dataFixed = Buffer.GetFixedBuffer()) { byte *start = dataFixed + Buffer.StartIndex; STREAM: using (outputStream) { RESET: currentOutputWaitType = outputWaitType; if (outputStream.Data.Byte != start) { outputStream.Reset(start, Buffer.Length); } buildInfo.Clear(); outputStream.Data.CurrentIndex = TcpServer.ServerOutput.OutputLink.StreamStartIndex; if ((head = Outputs.GetClear(out end)) == null) { goto CHECK; } 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; } CHECK: switch (currentOutputWaitType) { case TcpServer.OutputWaitType.ThreadYield: AutoCSer.Threading.ThreadYield.YieldOnly(); if (!Outputs.IsEmpty) { head = Outputs.GetClear(out end); currentOutputWaitType = TcpServer.OutputWaitType.DontWait; goto LOOP; } break; case TcpServer.OutputWaitType.ThreadSleep: System.Threading.Thread.Sleep(0); if (!Outputs.IsEmpty) { head = Outputs.GetClear(out end); currentOutputWaitType = TcpServer.OutputWaitType.DontWait; goto LOOP; } break; } if (buildInfo.Count == 0) { goto DISPOSE; } SETDATA: buildInfo.IsNewBuffer = setSendData(start, buildInfo.Count); 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) { goto RESET; } if (outputStream.Data.Byte != start) { outputStream.Reset(start, Buffer.Length); } buildInfo.Clear(); outputStream.Data.CurrentIndex = TcpServer.ServerOutput.OutputLink.StreamStartIndex; currentOutputWaitType = outputWaitType; 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.Exception(error, null, LogLevel.Exception | LogLevel.AutoCSer); buildInfo.IsError = true; } finally { if (buildInfo.IsError | buildInfo.IsClose) { if (buildInfo.IsError) { closeSocket(); } else { close(); } TcpServer.ServerOutput.OutputLink.CancelLink(head); } } } else { close(); } }
/// <summary> /// 发送数据 /// </summary> internal unsafe void BuildOutput() { if (IsSocket) { TcpServer.ServerOutput.OutputLink head = null, end; TcpServer.SenderBuildInfo buildInfo = new TcpServer.SenderBuildInfo { SendBufferSize = Server.SendBufferPool.Size }; UnmanagedStream outputStream; try { if (Buffer.Buffer == null) Server.SendBufferPool.Get(ref Buffer); if (OutputSerializer == null) outputStream = (OutputSerializer = BinarySerializer.YieldPool.Default.Pop() ?? new BinarySerializer()).SetTcpServer(); else outputStream = OutputSerializer.Stream; TcpServer.OutputWaitType outputWaitType = Server.ServerAttribute.OutputWaitType, currentOutputWaitType; do { buildInfo.IsNewBuffer = 0; fixed (byte* dataFixed = Buffer.GetFixedBuffer()) { byte* start = dataFixed + Buffer.StartIndex; STREAM: using (outputStream) { currentOutputWaitType = outputWaitType; if (outputStream.Data.Byte != start) outputStream.Reset(start, Buffer.Length); buildInfo.Clear(); outputStream.Data.CurrentIndex = TcpServer.ServerOutput.OutputLink.StreamStartIndex; 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: switch (currentOutputWaitType) { case TcpServer.OutputWaitType.ThreadYield: AutoCSer.Threading.ThreadYield.YieldOnly(); if (!Outputs.IsEmpty) { head = Outputs.GetClear(out end); currentOutputWaitType = TcpServer.OutputWaitType.DontWait; goto LOOP; } break; case TcpServer.OutputWaitType.ThreadSleep: System.Threading.Thread.Sleep(0); if (!Outputs.IsEmpty) { head = Outputs.GetClear(out end); currentOutputWaitType = TcpServer.OutputWaitType.DontWait; goto LOOP; } break; } if (buildInfo.Count == 0) { outputStream.Dispose(); goto END; } SEND: buildInfo.IsNewBuffer = setSendData(start, buildInfo.Count); } switch (send()) { case SendState.Asynchronous: return; case 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.Exception(error, null, LogLevel.Exception | LogLevel.AutoCSer); buildInfo.IsError = true; } finally { if (buildInfo.IsError | buildInfo.IsClose) { if (buildInfo.IsError) closeSocket(); else close(); TcpServer.ServerOutput.OutputLink.CancelLink(head); } } } else close(); }