示例#1
0
 /// <summary>
 ///		发送一个请求
 /// </summary>
 /// <param name="tx"></param>
 public void Send(IRpcTcpSendingPacket tx)
 {
     if (_closed)
     {
         ProcessSendFailed(new IRpcTcpSendingPacket[] { tx }, RpcErrorCode.SendFailed, null);
     }
     else
     {
         if (_connected && Interlocked.CompareExchange(ref _sending, 1, 0) == 0)
         {
             SendPackets(tx);
         }
         else
         {
             if (_pendingPackets.Count > RpcTcpBufferManager.SendPendingMax)
             {
                 ProcessSendFailed(new IRpcTcpSendingPacket[] { tx }, RpcErrorCode.SendPending, null);
             }
             else
             {
                 lock (_syncSend) {
                     _pendingPackets.Enqueue(tx);
                 }
                 _counter.SendPending.Increment();
             }
         }
     }
 }
示例#2
0
        private int GetExpectSize(IRpcTcpSendingPacket packet)
        {
            int bodySize = 0;

            if (packet.BodyBuffer != null)
            {
                bodySize = packet.BodyBuffer.GetSize();
            }
            return(bodySize + MaxHeaderSize);
        }
示例#3
0
        public static void WriteMessage(Stream stream, IRpcTcpSendingPacket p)
        {
            long begin = stream.Position;
            int  bodyLength;
            int  headerLength = 0;

            if (p.BodyBuffer == null)
            {
                bodyLength = -1;
            }
            else
            {
                bodyLength = p.BodyBuffer.GetSize() + 1;
            }

            byte[] headerBuffer = new byte[IdentityLength];
            stream.Write(headerBuffer, 0, IdentityLength);

            if (p.Direction == RpcMessageDirection.Request)
            {
                var h = p.RequestHeader;
                h.BodyLength = bodyLength;
                headerLength = (int)ProtoBufSerializer.Serialize(stream, h);
                SetInt32(headerBuffer, 0, IdentityMarkRequest);
            }
            else
            {
                var h = p.ResponseHeader;
                h.BodyLength = bodyLength;
                headerLength = (int)ProtoBufSerializer.Serialize(stream, h);
                SetInt32(headerBuffer, 0, IdentityMarkResponse);
            }
            int bodySize = 0;

            if (p.BodyBuffer != null)
            {
                p.BodyBuffer.TextError = true;
                bodySize = p.BodyBuffer.WriteToStream(stream);
            }
            long end = stream.Position;

            SetInt32(headerBuffer, 4, IdentityLength + headerLength + bodySize);
            SetInt16(headerBuffer, 8, headerLength);
            SetInt16(headerBuffer, 10, 0);

            stream.Seek(begin, SeekOrigin.Begin);
            stream.Write(headerBuffer, 0, IdentityLength);
            stream.Seek(end, SeekOrigin.Begin);
        }
示例#4
0
        private bool TryWriteBuffer(IRpcTcpSendingPacket packet, Stream stream, int remain)
        {
            int bodySize = 0;

            if (packet.BodyBuffer != null)
            {
                bodySize = packet.BodyBuffer.GetSize();
            }
            if (bodySize + MaxHeaderSize > remain)
            {
                _tracing.InfoFmt("Write Packet Not Enough {0} < {1}", bodySize, remain);
                return(false);
            }
            else
            {
                long begin = stream.Position;
                RpcTcpPacket.WriteMessage(stream, packet);
                _tracing.InfoFmt("Write Packet OK {0} remain {1}", stream.Position - begin, remain);
                return(true);
            }
        }
示例#5
0
        /// <summary>
        ///		发送报文
        ///		如果sendFirst == null, 则优先从queue中dequeue
        ///		否则, 先取出sendFirst, 然后再从queue中取
        ///		这是一个回调链,完全靠回调组织起来的,当_sending = 1时,存在一个回调链
        /// </summary>
        /// <param name="sendFirst"></param>
        private void SendPackets(IRpcTcpSendingPacket sendFirst)
        {
            int size;
            SocketAsyncEventArgs        eSend = null;
            List <IRpcTcpSendingPacket> batch = new List <IRpcTcpSendingPacket>();

            //
            // 阶段1. 获得第一个能够发送的报文
            try {
                //
                // 先至少放置一个报文进去
                if (sendFirst != null)
                {
                    batch.Add(sendFirst);
                }
                else
                {
                    if (_pendingPackets.Count == 0)
                    {
                        //
                        // 回调链的最终返回,只有当Queue完全清空以后,置空标记位
                        _sending = 0;
                        return;
                    }
                    else
                    {
                        lock (_syncSend) {
                            batch.Add(_pendingPackets.Dequeue());
                        }
                        _counter.SendPending.Decrement();
                    }
                }

                //
                // 获取第一个包的大小, 并估算对缓冲区的大小的需求
                size = GetExpectSize(batch[0]);
            } catch (Exception ex) {
                //
                // 在上面的代码块中如果出现异常,则本次发送失败
                _tracing.ErrorFmt(ex, "SendPackets 1 failed");
                ProcessSendFailed(batch, RpcErrorCode.SendFailed, ex);

                //
                // 扔出异常会导致连接断开,所以直接引发下一个调用链
                SendPackets(null);
                return;
            }


            //
            // 阶段2. 获取缓冲区,并写入数据
            try {
                //
                // 创建缓冲区, 如果过大会建立新缓冲区
                eSend = RpcTcpBufferManager.FetchSendArgs(size, _pendingPackets.Count);

                MemoryStream stream       = new MemoryStream(eSend.Buffer, 0, eSend.Buffer.Length, true, true);
                int          bufferRemain = eSend.Buffer.Length;

                //
                // 写入第一个报文
                TryWriteBuffer(batch[0], stream, bufferRemain);
                bufferRemain = bufferRemain - (int)stream.Position;

                //
                // 尝试向缓冲区内放置能够发送出去的最多的报文
                IRpcTcpSendingPacket packet = null;
                while (true)
                {
                    if (_pendingPackets.Count > 0)
                    {
                        lock (_syncSend) {
                            if (_pendingPackets.Count > 0)
                            {
                                packet = _pendingPackets.Dequeue();
                            }
                        }
                        _counter.SendPending.Decrement();
                    }
                    else
                    {
                        break;
                    }
                    int offsetBefore = (int)stream.Position;
                    if (TryWriteBuffer(packet, stream, bufferRemain))
                    {
                        batch.Add(packet);
                        packet = null;
                    }
                    else
                    {
                        break;
                    }
                    int offsetAfter = (int)stream.Position;
                    bufferRemain = bufferRemain - (offsetAfter - offsetBefore);
                }

                int bufferSize = (int)stream.Position;
                _counter.SendPerSec.Increment();
                _counter.SendTotal.Increment();

                _counter.SendMessageTotal.IncrementBy(batch.Count);
                _counter.SendMessagePerSec.IncrementBy(batch.Count);

                _counter.SendBytesPerSec.IncrementBy(bufferSize);
                _counter.SendBytesTotal.IncrementBy(bufferSize);

                eSend.UserToken = new SendingContext()
                {
                    NextPacket   = packet,
                    SendingBatch = batch,
                };

                if (eSend is RpcTcpAsyncArgs)
                {
                    ((RpcTcpAsyncArgs)eSend).Callback = delegate(SocketAsyncEventArgs e) {
                        ProcessSend(e);
                    };
                }
                else
                {
                    eSend.Completed += new EventHandler <SocketAsyncEventArgs>(
                        (sender, e) => ProcessSend(e)
                        );
                }

                eSend.SetBuffer(0, bufferSize);
            } catch (Exception ex) {
                //
                // 无论如何,先交回缓冲区
                RpcTcpBufferManager.Release(eSend);

                //
                // 在组织缓冲区的代码块中如果出现异常,则本次发送失败,整批失败
                _tracing.ErrorFmt(ex, "SendPackets 2 failed");
                ProcessSendFailed(batch, RpcErrorCode.SendFailed, ex);

                //
                // 扔出异常会导致连接断开,所以直接引发下一个调用链
                SendPackets(null);
                return;
            }

            if (!_socket.SendAsync(eSend))
            {
                ProcessSend(eSend);
            }
        }