// send a batch. internal so we can test it. internal void SendBatch(int channelId, Batch batch) { // get max batch size for this channel int max = Transport.activeTransport.GetMaxBatchSize(channelId); // we need a writer to merge queued messages into a batch using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) { // for each queued message while (batch.messages.Count > 0) { // get it PooledNetworkWriter message = batch.messages.Dequeue(); ArraySegment <byte> segment = message.ToArraySegment(); // IF adding to writer would end Up >= MTU then we should // flush first. the goal is to always flush < MTU packets. // // IMPORTANT: if writer is empty and segment is > MTU // (which can happen for large max sized message) // then we would send an empty previous writer. // => don't do that. // => only send if not empty. if (writer.Position > 0 && writer.Position + segment.Count >= max) { // flush & reset writer Transport.activeTransport.ServerSend(connectionId, channelId, writer.ToArraySegment()); writer.SetLength(0); } // now add to writer in any case // -> WriteBytes instead of WriteSegment because the latter // would add a size header. we want to write directly. // // NOTE: it's very possible that we add > MTU to writer if // message size is > MTU. // which is fine. next iteration will just flush it. writer.WriteBytes(segment.Array, segment.Offset, segment.Count); // return queued message to pool NetworkWriterPool.Recycle(message); } // done iterating queued messages. // batch might still contain the last message. // send it. if (writer.Position > 0) { Transport.activeTransport.ServerSend(connectionId, channelId, writer.ToArraySegment()); writer.SetLength(0); } } // reset send time for this channel's batch batch.lastSendTime = NetworkTime.time; }
public static PooledNetworkWriter GetWriter() { if (pool.Count != 0) { PooledNetworkWriter writer = pool.Pop(); // reset cached writer length and position writer.SetLength(0); return(writer); } return(new PooledNetworkWriter()); }