示例#1
0
        internal override void Send(ArraySegment <byte> segment, int channelId = Channels.DefaultReliable)
        {
            if (logger.LogEnabled())
            {
                logger.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));
            }

            //Debug.Log("ConnectionSend " + this + " bytes:" + BitConverter.ToString(segment.Array, segment.Offset, segment.Count));

            // validate packet size first.
            if (ValidatePacketSize(segment, channelId))
            {
                // batching? then add to queued messages
                if (batching)
                {
                    // put into a (pooled) writer
                    // -> WriteBytes instead of WriteSegment because the latter
                    //    would add a size header. we want to write directly.
                    // -> will be returned to pool when sending!
                    PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
                    writer.WriteBytes(segment.Array, segment.Offset, segment.Count);

                    // add to batch queue
                    Batch batch = GetBatchForChannelId(channelId);
                    batch.messages.Enqueue(writer);
                }
                // otherwise send directly to minimize latency
                else
                {
                    Transport.activeTransport.ServerSend(connectionId, channelId, segment);
                }
            }
        }
示例#2
0
        // add a new batch.
        // returns true if valid.
        // returns false if not, in which case the connection should be disconnected.
        public bool AddBatch(ArraySegment <byte> batch)
        {
            // IMPORTANT: ArraySegment is only valid until returning. we copy it!
            //
            // NOTE: it's not possible to create empty ArraySegments, so we
            //       don't need to check against that.

            // make sure we have at least 8 bytes to read for tick timestamp
            if (batch.Count < Batcher.HeaderSize)
            {
                return(false);
            }

            // put into a (pooled) writer
            // -> WriteBytes instead of WriteSegment because the latter
            //    would add a size header. we want to write directly.
            // -> will be returned to pool when sending!
            PooledNetworkWriter writer = NetworkWriterPool.GetWriter();

            writer.WriteBytes(batch.Array, batch.Offset, batch.Count);

            // first batch? then point reader there
            if (batches.Count == 0)
            {
                StartReadingBatch(writer);
            }

            // add batch
            batches.Enqueue(writer);
            //Debug.Log($"Adding Batch {BitConverter.ToString(batch.Array, batch.Offset, batch.Count)} => batches={batches.Count} reader={reader}");
            return(true);
        }
示例#3
0
        // 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;
        }
        // add a message for batching
        // we allow any sized messages.
        // caller needs to make sure they are within max packet size.
        public void AddMessage(ArraySegment <byte> message)
        {
            // put into a (pooled) writer
            // -> WriteBytes instead of WriteSegment because the latter
            //    would add a size header. we want to write directly.
            // -> will be returned to pool when making the batch!
            // IMPORTANT: NOT adding a size header / msg saves LOTS of bandwidth
            PooledNetworkWriter writer = NetworkWriterPool.GetWriter();

            writer.WriteBytes(message.Array, message.Offset, message.Count);
            messages.Enqueue(writer);
        }
示例#5
0
        // Send stage two: serialized NetworkMessage as ArraySegment<byte>
        internal override void Send(ArraySegment <byte> segment, int channelId = Channels.Reliable)
        {
            // get a writer to copy the message into since the segment is only
            // valid until returning.
            // => pooled writer will be returned to pool when dequeuing.
            // => WriteBytes instead of WriteArraySegment because the latter
            //    includes a 4 bytes header. we just want to write raw.
            //Debug.Log($"Enqueue {BitConverter.ToString(segment.Array, segment.Offset, segment.Count)}");
            PooledNetworkWriter writer = NetworkWriterPool.GetWriter();

            writer.WriteBytes(segment.Array, segment.Offset, segment.Count);
            connectionToServer.queue.Enqueue(writer);
        }