コード例 #1
0
        public void TestBase(
            IPacketFilter filter,
            int dataSize)
        {
            NetDataWriter writer = new NetDataWriter();

            byte[] data = GetData(dataSize);

            foreach (var item in data)
            {
                writer.Write(item);
            }

            NetPacket packet = NetPool.PacketPool.Alloc(PacketProperty.UserData, writer);

            var encodedPacket = filter.Encode(packet);
            var decodedPacket = filter.Decode(encodedPacket);

            NetDataReader reader = new NetDataReader(decodedPacket);

            Assert.GreaterOrEqual(decodedPacket.Size, packet.Size);

            for (int i = 0; i < data.Length; i++)
            {
                Assert.AreEqual(data[i], reader.ReadByte());
            }
        }
コード例 #2
0
        public override void SendAsync(NetPacket poolingPacket)
        {
            IPacketFilter filter = _channelOption.PacketFilter;

            while (filter != null)
            {
                poolingPacket = filter.Encode(poolingPacket);
                filter        = filter.NextFilter;
            }

            Interlocked.Increment(ref _statistic.TcpPacketSentCount);

            lock (_sendedList)
            {
                if (_sendedList.Count > 0)
                {
                    // 전송중임
                    _sendWaitQueue.Add(poolingPacket);
                    return;
                }

                _sendedBufferList.Push(new ArraySegment <byte>(poolingPacket.RawData, 0, poolingPacket.Size));
                _sendedList.Add(poolingPacket);
            }

            SendAsync(_sendedBufferList);
        }
コード例 #3
0
        public override void SendAsync(NetPacket poolingPacket)
        {
            var channel = GetChannel(poolingPacket.DeliveryMethod);
            if (channel == null)
            {
                NetPool.PacketPool.Free(poolingPacket);
                return;
            }

            int mtu = Mtu;
            if (poolingPacket.Size > mtu)
            {
                // 보낼수 있는 한계보다 큰 패킷이므로 쪼개서 보내자
                Interlocked.Increment(ref _statistic.UdpFragmentCount);

                try
                {
                    ushort currentFramentId = _fragments.GenerateId();

                    int headerSize = NetPacket.GetHeaderSize(poolingPacket.Property);
                    int dataSize = poolingPacket.Size - headerSize;

                    int maximumSize = mtu - headerSize;
                    int maximumDataSize = maximumSize - NetPacket.FragmentHeaderSize;
                    int totalPackets = dataSize / maximumDataSize + (dataSize % maximumDataSize == 0 ? 0 : 1);

                    for (ushort partIdx = 0; partIdx < totalPackets; partIdx++)
                    {
                        int sendLength = dataSize > maximumDataSize ? maximumDataSize : dataSize;

                        NetPacket p = NetPool.PacketPool.Alloc(sendLength + NetPacket.FragmentedHeaderTotalSize);
                        p.Property = poolingPacket.Property;
                        p.DeliveryMethod = poolingPacket.DeliveryMethod;
                        p.P2pSessionId = poolingPacket.P2pSessionId;
                        p.FragmentId = currentFramentId;
                        p.FragmentPart = partIdx;
                        p.FragmentsTotal = (ushort)totalPackets;
                        p.MarkFragmented();

                        Buffer.BlockCopy(poolingPacket.RawData, headerSize + partIdx * maximumDataSize, p.RawData, NetPacket.FragmentedHeaderTotalSize, sendLength);

                        IPacketFilter f = _channelOption.PacketFilter;
                        while (f != null)
                        {
                            p = f.Encode(p);
                            f = f.NextFilter;
                        }

                        channel.SendAsync(p);

                        dataSize -= sendLength;
                    }
                }
                finally
                {
                    NetPool.PacketPool.Free(poolingPacket);
                }

                return;
            }

            IPacketFilter filter = _channelOption.PacketFilter;
            while (filter != null)
            {
                poolingPacket = filter.Encode(poolingPacket);
                filter = filter.NextFilter;
            }

            Interlocked.Increment(ref _statistic.UdpPacketSentCount);

            channel.SendAsync(poolingPacket);
        }
コード例 #4
0
        public bool SendPendingPacket()
        {
            // 응답패킷을 보내야 한다면
            if (_sendAcks == true)
            {
                // lock에 비용이 많이드므로 먼저 체크한번 하고 나중에 또 체크하자
                lock (_ackPacket)
                {
                    if (_sendAcks == true)
                    {
                        _sendAcks = false;

                        IPacketFilter filter = _channelOption.PacketFilter;
                        if (filter != null)
                        {
                            var poolingPacket = NetPool.PacketPool.Alloc(_ackPacket, 0);
                            try
                            {
                                while (filter != null)
                                {
                                    poolingPacket = filter.Encode(poolingPacket);
                                    filter        = filter.NextFilter;
                                }

                                _udpChannel.SendTo(poolingPacket.RawData, 0, poolingPacket.Size, UdpChannel.SendMode.Buffered);
                            }
                            finally
                            {
                                NetPool.PacketPool.Free(poolingPacket);
                            }
                        }
                        else
                        {
                            _udpChannel.SendTo(_ackPacket.RawData, 0, _ackPacket.Size, UdpChannel.SendMode.Buffered);
                        }
                    }
                }
            }

            lock (_pendingPackets)
            {
                long nowTicks = DateTime.UtcNow.Ticks;

                lock (_sendQueue)
                {
                    while (_sendQueue.Count > 0)
                    {
                        int relate = NetUtil.RelativeSequenceNumber(_localSequence, _localWindowStart);
                        if (relate >= WindowSize)
                        {
                            break;
                        }

                        NetPacket packet = _sendQueue.Dequeue();

                        packet.Sequence = (ushort)_localSequence;
                        _pendingPackets[_localSequence % WindowSize].Init(packet, nowTicks);
                        _localSequence = (_localSequence + 1) % NetPacket.MaxSequence;
                    }
                }

                for (int pendingSeq = _localWindowStart; pendingSeq != _localSequence; pendingSeq = (pendingSeq + 1) % NetPacket.MaxSequence)
                {
                    if (_pendingPackets[pendingSeq % WindowSize].TrySend(
                            nowTicks,
                            _channelOption.RudpDisconnectTimeout,
                            _udpChannel,
                            _statistic) == false)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
コード例 #5
0
ファイル: SequencedChannel.cs プロジェクト: BestHatzker/EuNet
        public bool SendPendingPacket()
        {
            if (_reliable && _sendQueue.Count == 0)
            {
                long currentTime    = DateTime.UtcNow.Ticks;
                long packetHoldTime = currentTime - _lastPacketSendTime;
                if (packetHoldTime < _udpChannel.ResendDelay * TimeSpan.TicksPerMillisecond)
                {
                    return(true);
                }

                var packet = _lastPacket;
                if (packet != null)
                {
                    _lastPacketSendTime = currentTime;
                    _udpChannel.SendTo(packet.RawData, 0, packet.Size, UdpChannel.SendMode.Buffered);
                }
            }
            else
            {
                lock (_sendQueue)
                {
                    while (_sendQueue.Count > 0)
                    {
                        NetPacket packet = _sendQueue.Dequeue();
                        _localSequence  = (_localSequence + 1) % NetPacket.MaxSequence;
                        packet.Sequence = (ushort)_localSequence;

                        _udpChannel.SendTo(packet.RawData, 0, packet.Size, UdpChannel.SendMode.Buffered);

                        if (_reliable && _sendQueue.Count == 0)
                        {
                            _lastPacketSendTime = DateTime.UtcNow.Ticks;
                            _lastPacket         = packet;
                        }
                        else
                        {
                            NetPool.PacketPool.Free(packet);
                        }
                    }
                }
            }

            if (_reliable && _mustSendAck)
            {
                _mustSendAck        = false;
                _ackPacket.Sequence = _remoteSequence;

                IPacketFilter filter = _channelOption.PacketFilter;
                if (filter != null)
                {
                    var poolingPacket = NetPool.PacketPool.Alloc(_ackPacket, 0);
                    try
                    {
                        while (filter != null)
                        {
                            poolingPacket = filter.Encode(poolingPacket);
                            filter        = filter.NextFilter;
                        }

                        _udpChannel.SendTo(poolingPacket.RawData, 0, poolingPacket.Size, UdpChannel.SendMode.Buffered);
                    }
                    finally
                    {
                        NetPool.PacketPool.Free(poolingPacket);
                    }
                }
                else
                {
                    _udpChannel.SendTo(_ackPacket.RawData, 0, _ackPacket.Size, UdpChannel.SendMode.Buffered);
                }
            }

            return(true);
        }