⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rudpsocket.cs

📁 rudp可靠保障得udp传输
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;

using Helper.Threading.Collections;

namespace Helper.Net.RUDP
{

	#region RUDPSocketStatus

	internal enum RUDPSocketStatus
	{
		Connecting,		// During the connection phase
		Connected,		// We are connected
		Closing,		// During the closing phase
		ClosingACKed,	// When the tear down message has been ACKed
		Closed,			// The connection is closed / It is the default status
		Accepting
	}

	#endregion

	#region RUDPSocketError

	/// <summary>
	/// For more information about socket errors :
	/// http://support.microsoft.com/default.aspx?scid=kb;en-us;819124
	/// </summary>
	public enum RUDPSocketError
	{
		// Summary:
		//     An unspecified System.Net.Sockets.ServerSocket error has occurred.
		SocketError = -1,
		//
		// Summary:
		//     The System.Net.Sockets.ServerSocket operation succeeded.
		Success = 0,
		//
		// Summary:
		//     The overlapped operation was aborted due to the closure of the System.Net.Sockets.ServerSocket.
		//OperationAborted = 995,
		//
		// Summary:
		//     The application has initiated an overlapped operation that cannot be completed
		//     immediately.
		//IOPending = 997,
		//
		// Summary:
		//     A blocking System.Net.Sockets.ServerSocket call was canceled.
		//Interrupted = 10004,
		//
		// Summary:
		//     An attempt was made to access a System.Net.Sockets.ServerSocket in a way that is
		//     forbidden by its access permissions.
		//AccessDenied = 10013,
		//
		// Summary:
		//     An invalid pointer address was detected by the underlying socket provider.
		//Fault = 10014,
		//
		// Summary:
		//     An invalid argument was supplied to a System.Net.Sockets.ServerSocket member.
		//InvalidArgument = 10022,
		//
		// Summary:
		//     There are too many open sockets in the underlying socket provider.
		//TooManyOpenSockets = 10024,
		//
		// Summary:
		//     An operation on a nonblocking socket cannot be completed immediately.
		//WouldBlock = 10035,
		//
		// Summary:
		//     A blocking operation is in progress.
		InProgress = 10036,
		//
		// Summary:
		//     The nonblocking System.Net.Sockets.ServerSocket already has an operation in progress.
		AlreadyInProgress = 10037,
		//
		// Summary:
		//     A System.Net.Sockets.ServerSocket operation was attempted on a non-socket.
		//NotSocket = 10038,
		//
		// Summary:
		//     A required address was omitted from an operation on a System.Net.Sockets.ServerSocket.
		//DestinationAddressRequired = 10039,
		//
		// Summary:
		//     The datagram is too long.
		//MessageSize = 10040,
		//
		// Summary:
		//     The protocol type is incorrect for this System.Net.Sockets.ServerSocket.
		//ProtocolType = 10041,
		//
		// Summary:
		//     An unknown, invalid, or unsupported option or level was used with a System.Net.Sockets.ServerSocket.
		//ProtocolOption = 10042,
		//
		// Summary:
		//     The protocol is not implemented or has not been configured.
		//ProtocolNotSupported = 10043,
		//
		// Summary:
		//     The support for the specified socket type does not exist in this address
		//     family.
		//SocketNotSupported = 10044,
		//
		// Summary:
		//     The address family is not supported by the protocol family.
		//OperationNotSupported = 10045,
		//
		// Summary:
		//     The protocol family is not implemented or has not been configured.
		//ProtocolFamilyNotSupported = 10046,
		//
		// Summary:
		//     The address is incompatible with the requested protocol.
		//AddressFamilyNotSupported = 10047,
		//
		// Summary:
		//     Only one use of an address is normally permitted.
		//AddressAlreadyInUse = 10048,
		//
		// Summary:
		//     The selected address is valid in this context.
		//AddressNotAvailable = 10049,
		//
		// Summary:
		//     The network is not available.
		NetworkDown = 10050,
		//
		// Summary:
		//     No route to the remote host exists.
		NetworkUnreachable = 10051,
		//
		// Summary:
		//     The application tried to set System.Net.Sockets.SocketOptionName.KeepAlive
		//     on a connection that has already timed out.
		NetworkReset = 10052,
		//
		// Summary:
		//     The connection was aborted by the .NET Framework or the underlying socket
		//     provider.
		//ConnectionAborted = 10053,
		//
		// Summary:
		//     The connection was reset by the remote peer.
		ConnectionReset = 10054,
		//
		// Summary:
		//     No free buffer space is available for a System.Net.Sockets.ServerSocket operation.
		NoBufferSpaceAvailable = 10055,
		//
		// Summary:
		//     The System.Net.Sockets.ServerSocket is already connected.
		IsConnected = 10056,
		//
		// Summary:
		//     The application tried to send or receive data, and the System.Net.Sockets.ServerSocket
		//     is not connected.
		NotConnected = 10057,
		//
		// Summary:
		//     A request to send or receive data was disallowed because the System.Net.Sockets.ServerSocket
		//     has already been closed.
		Shutdown = 10058,
		//
		// Summary:
		//     The connection attempt timed out, or the connected host has failed to respond.
		TimedOut = 10060,
		//
		// Summary:
		//     The remote host is actively refusing a connection.
		ConnectionRefused = 10061,
		//
		// Summary:
		//     The operation failed because the remote host is down.
		HostDown = 10064,
		//
		// Summary:
		//     There is no network route to the specified host.
		HostUnreachable = 10065,
		//
		// Summary:
		//     Too many processes are using the underlying socket provider.
		ProcessLimit = 10067,
		//
		// Summary:
		//     The network subsystem is unavailable.
		SystemNotReady = 10091,
		//
		// Summary:
		//     The version of the underlying socket provider is out of range.
		//VersionNotSupported = 10092,
		//
		// Summary:
		//     The underlying socket provider has not been initialized.
		NotInitialized = 10093,
		//
		// Summary:
		//     A graceful shutdown is in progress.
		Disconnecting = 10101,
		//
		// Summary:
		//     The specified class was not found.
		//TypeNotFound = 10109,
		//
		// Summary:
		//     No such host is known. The name is not an official host name or alias.
		HostNotFound = 11001,
		//
		// Summary:
		//     The name of the host could not be resolved. Try again later.
		//TryAgain = 11002,
		//
		// Summary:
		//     The error is unrecoverable or the requested database cannot be located.
		//NoRecovery = 11003,
		//
		// Summary:
		//     The requested name or IP address was not found on the name server.
		NoData = 11004,
	}

	#endregion

	#region RUDPSocketException

	sealed public class RUDPSocketException : Exception
	{
		public RUDPSocketError Error;

		public RUDPSocketException(RUDPSocketError error)
		{
			Error = error;
		}
	}

	#endregion

	#region RUDPSocketNetworkInformation

	sealed public class RUDPSocketNetworkInformation
	{

		#region Variables

		private RUDPSocket _rudp;

		#endregion

		#region Constructor

		internal RUDPSocketNetworkInformation(RUDPSocket rudp)
		{
			_rudp = rudp;
		}

		#endregion

		#region Properties

		public int PathMTU
		{
			get
			{
				return _rudp._mtu;
			}
		}

		public double SendCongestionWindow
		{
			get
			{
				return _rudp._controlWindow._cwnd;
			}
		}

		public double RTT
		{
			get
			{
				return _rudp._rtt;
			}
		}

		public double RTO
		{
			get
			{
				return _rudp._rto;
			}
		}

		/// <summary>
		/// Estimated Bandwidth in Bytes/Milli-seconds
		/// </summary>
		public long BandWidth
		{
			get
			{
				return _rudp._bandwidth;
			}
		}

		#endregion

	}

	#endregion

	#region RUDPCongestionControl

	public enum RUDPCongestionControl
	{
		TCPReno,
		TCPBIC,
		TCPCUBIC,
		UDT,

		Simple01
	}

	#endregion

	sealed public class RUDPSocket
	{

		#region Variables

		//---- Global
		static internal int LockTimeOut = -1;

		static internal int DefaultConnectionTimeOut = 60000;

		static internal int LastHandle = 0;

		//---- ServerSocket data
		internal PhysicalSocket _physical;
		internal IPEndPoint _remoteEndPoint;
		internal bool _isRendezVousMode = false;

		//---- State of the socket
		internal RUDPSocketStatus _status = RUDPSocketStatus.Closed;
		internal bool _isShutingDown = false;

		//---- An internal handle
		internal int _handle;

		//----- Asynchronous call datas
		internal RUDPAcceptIAsyncResult _asyncResultAccept;
		internal RUDPConnectIAsyncResult _asyncResultConnect;
		internal RUDPReceiveIAsyncResult _asyncResultReceive;

		//----- Identify a byte in the flow (like TCP)
		internal long _sequence = 0;

		//---- List of outgoing and ingoing packets
		internal ReaderWriterLock _sendingPacketsLock = new ReaderWriterLock();
		internal List<RUDPOutgoingPacket> _sendingPackets = new List<RUDPOutgoingPacket>();

		// incoming packets
		internal Object _incomingPacketsLock = new Object();
		internal SortedList _incomingPackets = new SortedList();
		internal LockFreeQueue<RUDPIngoingPacket> _incomingNonReliablePackets = new LockFreeQueue<RUDPIngoingPacket>();

		//---- List of incoming connections sockets
		internal List<RUDPSocket> _acceptedRUDPSockets = new List<RUDPSocket>();

		//---- List of outgoing and ingoing messages
		internal int _ougoingPacketId;

		internal int _incomingPacketId;

		//---- Receive / Send size
		internal int _receiveSize = 100 * 1024;
		internal int _sendSize = 100 * 1024;

		//---- ACKs management
		internal SACKWindow _sackWindow;

		// Last time an ACK has been sended
		internal long _lastACKSendTS = -1;

		//---- MTU
		internal bool _usePMTUDiscovery = true;
		internal PMTUDiscovery _pmtuDiscovery;
		internal int _mtu = -1;

		//---- Time Stamp : Last time we send a packet
		internal long _lastSendTS;

		//---- Time Stamp : for bandwidth calculation
		internal long _lastBandwidthTS;
		internal long _bandwidthResponse01TS;
		internal long _bandwidth; // byte / ms

		//---- RTT & Time outs

		// RTT (Round Trip Time: time needed to send a message and receive its ACK)
		internal double _rtt;

		// RTO (Retransmission Time Out)
		internal double _rto;

		// Delta RTT (RTT difference)
		internal double _deltaRtt;

		// STO (send Time Out)
		internal long _sto;

		//---- Windows
		internal AbstractWindow _controlWindow;

		//---- Some statistics
		private RUDPSocketNetworkInformation _networkInformation;
#if STATISTICS
		internal int Stats_ReceivedMessagesCount = 0;
		internal int Stats_SendedMessagesCount = 0;
		internal int Stats_ResendedMessagesCount = 0;
		internal int Stats_SendedACKCount = 0;
		internal int Stats_LastQueuedSendedACKId = 0;
		internal int Stats_LastSendedACKId = 0;
		internal int Stats_ReceivedACKCount = 0;
		internal int Stats_LastReceivedACKId = 0;
#endif
		#endregion

		#region Constructor

		public RUDPSocket()
			: this(RUDPCongestionControl.TCPReno)
		{
		}

		public RUDPSocket(RUDPCongestionControl congestionControl)
		{
			switch (congestionControl)
			{
				case RUDPCongestionControl.TCPReno:
					_controlWindow = new Helper.Net.RUDP.Reno.CongestionWindow(this);
					break;
				case RUDPCongestionControl.TCPBIC:
					_controlWindow = new Helper.Net.RUDP.BIC.CongestionWindow(this);
					break;
				case RUDPCongestionControl.TCPCUBIC:
					_controlWindow = new Helper.Net.RUDP.CUBIC.CongestionWindow(this);
					break;
				case RUDPCongestionControl.UDT:
					_controlWindow = new Helper.Net.RUDP.UDT.CongestionWindow(this);
					break;
				case RUDPCongestionControl.Simple01:
					_controlWindow = new Helper.Net.RUDP.Simple01.CongestionWindow(this);
					break;
			}

			//---- Reset
			Reset(RUDPSocketStatus.Closed);

			//---- Update handle
			_handle = LastHandle;
			LastHandle++;

			//---- Setup network information
			_networkInformation = new RUDPSocketNetworkInformation(this);
		}

		internal void Reset(RUDPSocketStatus status)
		{
			RUDPStack.Trace("RESET PeerInformation");

			//---- Reset all
			_status = status;

			_ougoingPacketId = -1;
			_incomingPacketId = -1;

			_sequence = 0;

			_lastSendTS = 0;
			_lastACKSendTS = -1;

			_lastBandwidthTS = 0;
			_bandwidthResponse01TS = 0;
			_bandwidth = 0;

			_sendingPacketsLock.AcquireWriterLock(RUDPSocket.LockTimeOut);
			for (int index = 0; index < _sendingPackets.Count; index++)
				RUDPStack.ReleaseOutgoingPacket(_sendingPackets[index]);
			_sendingPackets.Clear();
			_sendingPacketsLock.ReleaseWriterLock();

			lock (_incomingPacketsLock)
				_incomingPackets.Clear();

			_incomingNonReliablePackets.Clear();

			_sackWindow = new SACKWindow();
			_pmtuDiscovery = new PMTUDiscovery(this);
			_controlWindow.Reset();
		}

		#endregion

		#region Bind

		public void Bind(IPEndPoint endPoint)
		{
			// Get the associated physical socket
			_physical = RUDPStack.GetInstance(endPoint);
		}

		private void AutomaticBind()
		{
			IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
			Bind(endPoint);
		}

		#endregion

		#region Listen

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -