/// <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();
 }
Example #2
0
        /// <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();
            }
        }