/// <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(); } } } }
private int GetExpectSize(IRpcTcpSendingPacket packet) { int bodySize = 0; if (packet.BodyBuffer != null) { bodySize = packet.BodyBuffer.GetSize(); } return(bodySize + MaxHeaderSize); }
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); }
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); } }
/// <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); } }