RUDPFramework/Assets/Scripts/Network/NetworkTransport/ClientSession.cs

193 lines
5.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
namespace Network.NetworkTransport
{
public class ClientSession
{
private ITransport _transport;
private IPEndPoint _remote;
public long LastActivityTs { get; private set; }
public uint SendSequenceNumber { get; private set; } = 0;
private int _currentTicks = 0;
private int _nextSendTicks = 0;
private int _sendInterval = 10;
// 重传时间 5s
private long _retransmitTicks = 5000;
// 上层交付
private readonly LinkedList<Packet> _sendQueue = new LinkedList<Packet>();
// 已发送但未确认
private readonly LinkedList<Packet> _sendBuffer = new LinkedList<Packet>();
// 已收到但乱序
private readonly LinkedList<Packet> _receiveBuffer = new LinkedList<Packet>();
// 已收到可交付
private readonly LinkedList<Packet> _receiveQueue = new LinkedList<Packet>();
private bool _hasReceived = false;
private uint _expectedAck = 0;
private readonly object _lockObj = new object();
public ClientSession(ITransport transport, IPEndPoint remote)
{
_transport = transport;
_remote = remote;
LastActivityTs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
}
public uint GetExpectedAck() => _expectedAck;
public void SetSendInterval(int interval) => _sendInterval = interval;
private uint GetNextSendSequence()
{
lock (_lockObj)
{
return SendSequenceNumber++;
}
}
public void Tick(int currentTicks)
{
_currentTicks = currentTicks;
if (_currentTicks >= _nextSendTicks)
{
_nextSendTicks = currentTicks + _sendInterval;
SendPacketInternal();
}
}
public void SendPacket(byte[] data)
{
_sendQueue.AddLast(Packet.CreateDataPacket(GetNextSendSequence(), data));
}
public List<Packet> ReceivePackets()
{
var list = new List<Packet>();
lock (_lockObj)
{
while (_receiveQueue.Count > 0)
{
var packet = _receiveQueue.First.Value;
list.Add(packet);
_receiveQueue.RemoveFirst();
}
}
return list;
}
private void SendPacketInternal()
{
if (_hasReceived)
{
var packet = Packet.CreateAckPacket(_expectedAck);
_sendBuffer.AddLast(packet);
var bytes = packet.ToBytes();
_transport.SendTo(bytes, _remote);
_hasReceived = false;
}
foreach (var packet in _receiveBuffer)
{
if (_currentTicks - packet.Timestamp > _retransmitTicks)
{
var bytes = packet.ToBytes();
_transport.SendTo(bytes, _remote);
}
else break;
}
while (_sendQueue.Count > 0)
{
var packet = _sendQueue.First.Value;
_sendBuffer.AddLast(packet);
var bytes = packet.ToBytes();
_transport.SendTo(bytes, _remote);
}
}
public void ReceivePacketsInternal(Packet packet)
{
uint seq = packet.SequenceNumber;
// 是否是按序到达的包
if (seq == _expectedAck)
{
_receiveQueue.AddLast(packet);
while (_receiveBuffer.Count > 0)
{
var pendingPacket = _receiveBuffer.First.Value;
if (seq != pendingPacket.SequenceNumber) break;
seq++;
_receiveQueue.AddLast(pendingPacket);
_receiveBuffer.RemoveFirst();
}
_expectedAck = seq + 1;
_hasReceived = true;
}
// 将包按顺序追加在 receivingPackets 后面
else
{
var firstNode = _receiveBuffer.First;
while (firstNode.Next != null)
{
if (firstNode.Value.SequenceNumber > seq)
{
var node = new LinkedListNode<Packet>(packet);
_receiveBuffer.AddBefore(firstNode, node);
break;
}
firstNode = firstNode.Next;
}
if (firstNode == null) _receiveBuffer.AddLast(packet);
}
}
public bool TryProcessReceiveSequence(uint sequenceNumber, out bool shouldDeliver)
{
lock (_lockObj)
{
LastActivityTs = DateTime.Now;
if (sequenceNumber == _expectedAck)
{
_expectedAck++;
_receivedSequences.Add(sequenceNumber);
shouldDeliver = true;
return true;
}
else if (sequenceNumber < _expectedAck)
{
shouldDeliver = false;
return _receivedSequences.Contains(sequenceNumber);
}
else
{
shouldDeliver = false;
return false;
}
}
}
}
}