All pastes #761574 Raw Edit

tobz

public text v1 · immutable
·published 2007-11-04 23:35 UTC
rendered paste body
public abstract class ClientBase
    {
		public class ProcessDataExecObj : IExecObj
		{
			private ClientBase m_client;
			private int m_bytesReceived = 0;

			public ProcessDataExecObj()
			{
			}

			public ClientBase Client
			{
				set
				{
					m_client = value;
				}
			}

			public int BytesReceived
			{
				get
				{
					return m_bytesReceived;
				}
				set
				{
					m_bytesReceived = value;
				}
			}

			public void Execute()
			{
				m_client.OnReceive(m_bytesReceived);
				m_client.ResumeReceive();
			}
		}

        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="server">The server this client is connected to.</param>
        protected ClientBase(ServerBase server)
        {
            m_server = server;

            m_readBuffer = BufferManager.Instance.CheckOut();

			m_processDataObj = new ProcessDataExecObj();
			m_processDataObj.Client = this;
        }

        #region Private variables

        /// <summary>
        /// Total number of bytes that have been received by all clients.
        /// </summary>
        private static volatile uint s_totalBytesReceived;

        /// <summary>
        /// Total number of bytes that have been sent by all clients.
        /// </summary>
        private static volatile uint s_totalBytesSent;

        /// <summary>
        /// Number of bytes that have been received by this client.
        /// </summary>
        private int m_bytesReceived;

        /// <summary>
        /// Number of bytes that have been sent by this client.
        /// </summary>
        private int m_bytesSent;

        /// <summary>
        /// The socket containing the TCP connection this client is using.
        /// </summary>
        protected Socket m_tcpSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        /// <summary>
        /// Pointer to the server this client is connected to.
        /// </summary>
        protected ServerBase m_server;

        /// <summary>
        /// The port the client should receive UDP datagrams on.
        /// </summary>
        protected IPEndPoint m_udpEp;

        /// <summary>
        /// The buffer containing the data received.
        /// </summary>
        protected ArraySegment<byte> m_readBuffer;

        /// <summary>
        /// The adjustment to make in the packet buffer.
        /// </summary>
        protected int m_packetDelta;

		/// <summary>
		/// The execution object for processing data.
		/// </summary>
		protected ProcessDataExecObj m_processDataObj;

        #endregion

        #region Public properties

        public ServerBase Server
        {
            get { return m_server; }
        }

        /// <summary>
        /// Gets the total number of bytes sent to all clients.
        /// </summary>
        [CLSCompliant(false)]
        public static uint TotalBytesSent
        {
            get { return s_totalBytesSent; }
        }

        /// <summary>
        /// Gets the total number of bytes received by all clients.
        /// </summary>
        [CLSCompliant(false)]
        public static uint TotalBytesReceived
        {
            get { return s_totalBytesReceived; }
        }

        /// <summary>
        /// Gets the IP address of the client.
        /// </summary>
        public IPAddress TcpIP
        {
            get { return (m_tcpSock.RemoteEndPoint as IPEndPoint).Address; }
        }

        /// <summary>
        /// Gets the port the client is communicating on.
        /// </summary>
        public int TcpPort
        {
            get { return (m_tcpSock.RemoteEndPoint as IPEndPoint).Port; }
        }

        /// <summary>
        /// Gets the port the client should receive UDP datagrams on.
        /// </summary>
        public IPEndPoint UdpEndpoint
        {
            get { return m_udpEp; }
            set { m_udpEp = value; }
        }

        /// <summary>
        /// Gets/Sets the socket this client is using for TCP communication.
        /// </summary>
        public Socket TcpSocket
        {
            get { return m_tcpSock; }
            set
            {
                if (m_tcpSock.Connected)
                {
                    m_tcpSock.Shutdown(SocketShutdown.Both);
                    m_tcpSock.Close();
                }

                if (value != null)
                {
                    m_tcpSock = value;
                }
            }
        }

        #endregion

        /// <summary>
        /// Begins asynchronous TCP receiving for this client.
        /// </summary>
        public void BeginReceive()
        {
            if (m_tcpSock.Connected)
            {
                using (SocketAsyncEventArgs args = new SocketAsyncEventArgs())
                {
                    args.SetBuffer(m_readBuffer.Array, m_readBuffer.Offset, m_readBuffer.Count);
                    args.UserToken = this;
                    args.Completed += ReceiveAsyncComplete;

                    m_tcpSock.ReceiveAsync(args);
                }
            }
        }

		/// <summary>
		/// Resumes asynchronous TCP receiving for this client.
		/// </summary>
		public void ResumeReceive()
		{
			using (SocketAsyncEventArgs socketArgs = new SocketAsyncEventArgs())
			{
				socketArgs.SetBuffer(m_readBuffer.Array, m_readBuffer.Offset + m_packetDelta, m_readBuffer.Count - m_packetDelta);
				socketArgs.UserToken = this;
				socketArgs.Completed += ReceiveAsyncComplete;

				m_tcpSock.ReceiveAsync(socketArgs);
			}
		}

        private static void ReceiveAsyncComplete(object sender, SocketAsyncEventArgs args)
        {
            ClientBase client = args.UserToken as ClientBase;

            try
            {
                int bytesTransferred = args.BytesTransferred;

                if (bytesTransferred == 0)
                {
                    client.m_server.DisconnectClient(client, true);
                }
                else
                {
                    unchecked
                    {
                        client.m_bytesReceived += bytesTransferred;
                        s_totalBytesReceived += (uint)bytesTransferred;
                    }

					client.m_processDataObj.BytesReceived = bytesTransferred;

					ThreadMgr.QueueExecObj(client.m_processDataObj);
                }
            }
            catch (ObjectDisposedException e)
            {
                client.m_server.Warning(client, e);
                client.m_server.DisconnectClient(client, true);
            }
            catch (Exception e)
            {
                client.m_server.Warning(client, e);
                client.m_server.DisconnectClient(client, true);
            }
        }

        /// <summary>
        /// Called when a packet has been received and needs to be processed.
        /// </summary>
        /// <param name="num_bytes">The size of the packet in bytes.</param>
        protected abstract void OnReceive(int num_bytes);
}