首页 > 代码库 > 介绍开源的.net通信框架NetworkComms框架 源码分析(二十三 )TCPConnection

介绍开源的.net通信框架NetworkComms框架 源码分析(二十三 )TCPConnection

原文网址: http://www.cnblogs.com/csdev

Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是:Apache License v2

开源地址是:https://github.com/MarcFletcher/NetworkComms.Net

/// <summary>    /// A connection object which utilises <see href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</see> to communicate between peers.    /// Tcp连接对象   通过TCP协议在端点之间通信    /// </summary>    public sealed partial class TCPConnection : IPConnection    {#if WINDOWS_PHONE || NETFX_CORE        /// <summary>        /// The windows phone socket corresponding to this connection.        /// </summary>        StreamSocket socket;#else        /// <summary>        /// The TcpClient corresponding to this connection.        /// 与此连接相关的TcpClient对象        /// </summary>        TcpClient tcpClient;        /// <summary>        /// The networkstream associated with the tcpClient.        /// 与tcpClient相对应额networkstream对象        /// </summary>        Stream connectionStream;                /// <summary>        /// The SSL options associated with this connection.        /// SSL(安全套接层) 相关的参数设置        /// </summary>        public SSLOptions SSLOptions { get; private set; }#endif        /// <summary>        /// The current incoming data buffer        ///  进入的数据的缓冲区        /// </summary>        byte[] dataBuffer;        /// <summary>        /// TCP connection constructor        /// TCP连接构造器        /// </summary>#if WINDOWS_PHONE || NETFX_CORE        private TCPConnection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions, StreamSocket socket)#else        private TCPConnection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions, TcpClient tcpClient, SSLOptions sslOptions)#endif            : base(connectionInfo, defaultSendReceiveOptions)        {            if (connectionInfo.ConnectionType != ConnectionType.TCP)                throw new ArgumentException("Provided connectionType must be TCP.", "connectionInfo");            dataBuffer = new byte[NetworkComms.InitialReceiveBufferSizeBytes];            //We don‘t guarantee that the tcpClient has been created yet            //在构造器中  tcpClient对象可能还没有被创建#if WINDOWS_PHONE || NETFX_CORE            if (socket != null) this.socket = socket;#else            if (tcpClient != null) this.tcpClient = tcpClient;            this.SSLOptions = sslOptions;#endif        }        /// <inheritdoc />        /// 创建Tcp连接        protected override void EstablishConnectionSpecific()        {#if WINDOWS_PHONE || NETFX_CORE            if (socket == null) ConnectSocket();            //For the local endpoint            //本地端点            var localEndPoint = new IPEndPoint(IPAddress.Parse(socket.Information.LocalAddress.CanonicalName.ToString()), int.Parse(socket.Information.LocalPort));            //We should now be able to set the connectionInfo localEndPoint            //此处 可以设置connectionInfo对象的本地端点            NetworkComms.UpdateConnectionReferenceByEndPoint(this, ConnectionInfo.RemoteIPEndPoint, localEndPoint);            ConnectionInfo.UpdateLocalEndPointInfo(localEndPoint);            //Set the outgoing buffer size            //设置发送缓冲区大小            socket.Control.OutboundBufferSizeInBytes = (uint)NetworkComms.SendBufferSizeBytes;#else            if (tcpClient == null) ConnectSocket();            //We should now be able to set the connectionInfo localEndPoint            //我们现在应该能够设置 connectionInfo对象的本地端点            NetworkComms.UpdateConnectionReferenceByEndPoint(this, ConnectionInfo.RemoteIPEndPoint, (IPEndPoint)tcpClient.Client.LocalEndPoint);            ConnectionInfo.UpdateLocalEndPointInfo((IPEndPoint)tcpClient.Client.LocalEndPoint);            if (SSLOptions.SSLEnabled)                ConfigureSSLStream();            else                //We are going to be using the networkStream quite a bit so we pull out a reference once here                //networkStream类型的网络流 后面会有不少地方需要使用 此处做一个引用                connectionStream = tcpClient.GetStream();            //When we tell the socket/client to close we want it to do so immediately  当我们告诉socket/client关闭时 我们希望其立即关闭            //this.tcpClient.LingerState = new LingerOption(false, 0);            //We need to set the keep alive option otherwise the connection will just die at some random time should we not be using it            //我们需要设定Keep alive选项 以防止连接断开  (后来没有使用)            //NOTE: This did not seem to work reliably so was replaced with the keepAlive packet feature            //注意:设定KeepAlive选项来维护Tcp连接并不可靠   所以后来我们用发送心跳包进行代替              //this.tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);            tcpClient.ReceiveBufferSize = NetworkComms.MaxReceiveBufferSizeBytes;            tcpClient.SendBufferSize = NetworkComms.SendBufferSizeBytes;            //This disables the ‘nagle algorithm‘ 禁用 nagle算法            //http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.nodelay.aspx            //Basically we may want to send lots of small packets (<200 bytes) and sometimes those are time critical (e.g. when establishing a connection)            //If we leave this enabled small packets may never be sent until a suitable send buffer length threshold is passed. i.e. BAD            //下面的2个选项设定为true,当Tcp连接上有数据时,立即发送,我符合我们的预期。而不是等待Tcp缓冲池中有足够多的数据才一起发送            tcpClient.NoDelay = true;            tcpClient.Client.NoDelay = true;#endif            //Start listening for incoming data            //开始监听进来的数据            StartIncomingDataListen();            //If the application layer protocol is enabled we handshake the connection            //如果应用层协议启用 连接进行握手操作            //应用层协议,系统默认为启用             if (ConnectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled)                ConnectionHandshake();            else            {                //If there is no handshake we can now consider the connection established                //如果此处无握手操作 我们可以考虑创建连接                TriggerConnectionEstablishDelegates();                //Trigger any connection setup waits                //触发任何连接建设等待                connectionSetupWait.Set();            }#if !WINDOWS_PHONE && !NETFX_CORE            //Once the connection has been established we may want to re-enable the ‘nagle algorithm‘ used for reducing network congestion (apparently).            //By default we leave the nagle algorithm disabled because we want the quick through put when sending small packets            //一旦连接建立了,某些情况下我们可能要重新启用“Nagle算法”用于减少网络拥塞。            //默认情况下我们不启用 nagle 算法,启用nagle算法将导致小的数据不能被及时的发送            if (EnableNagleAlgorithmForNewConnections)            {                tcpClient.NoDelay = false;                tcpClient.Client.NoDelay = false;            }#endif        }        /// <summary>        /// If we were not provided with a tcpClient on creation we need to create one        /// 如果没有tcpClient对象则创建一个        /// </summary>        private void ConnectSocket()        {            try            {                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace("Connecting TCP client with " + ConnectionInfo);                bool connectSuccess = true;#if WINDOWS_PHONE || NETFX_CORE                //We now connect to our target                //我们现在开始连接到我们的目标                socket = new StreamSocket();                socket.Control.NoDelay = !EnableNagleAlgorithmForNewConnections;                CancellationTokenSource cancelAfterTimeoutToken = new CancellationTokenSource(NetworkComms.ConnectionEstablishTimeoutMS);                try                {                    if (ConnectionInfo.LocalEndPoint != null && ConnectionInfo.LocalIPEndPoint.Address != IPAddress.IPv6Any && ConnectionInfo.LocalIPEndPoint.Address != IPAddress.Any)                    {                                                var endpointPairForConnection = new Windows.Networking.EndpointPair(new Windows.Networking.HostName(ConnectionInfo.LocalIPEndPoint.Address.ToString()), ConnectionInfo.LocalIPEndPoint.Port.ToString(),                                                        new Windows.Networking.HostName(ConnectionInfo.RemoteIPEndPoint.Address.ToString()), ConnectionInfo.RemoteIPEndPoint.Port.ToString());                                                var task = socket.ConnectAsync(endpointPairForConnection).AsTask(cancelAfterTimeoutToken.Token);                        task.Wait();                    }                    else                    {                        var task = socket.ConnectAsync(new Windows.Networking.HostName(ConnectionInfo.RemoteIPEndPoint.Address.ToString()), ConnectionInfo.RemoteIPEndPoint.Port.ToString()).AsTask(cancelAfterTimeoutToken.Token);                        task.Wait();                    }                }                catch (Exception)                {                    socket.Dispose();                    connectSuccess = false;                }#else                //We now connect to our target                //我们现在开始连接到我们的目标                tcpClient = new TcpClient(ConnectionInfo.RemoteEndPoint.AddressFamily);                //Start the connection using the async version                //以异步方式开始连接                //This allows us to choose our own connection establish timeout                //允许设定连接创建超时时间                IAsyncResult ar = tcpClient.BeginConnect(ConnectionInfo.RemoteIPEndPoint.Address, ConnectionInfo.RemoteIPEndPoint.Port, null, null);                WaitHandle connectionWait = ar.AsyncWaitHandle;                try                {                    if (!connectionWait.WaitOne(NetworkComms.ConnectionEstablishTimeoutMS, false))                        connectSuccess = false;                    else                        tcpClient.EndConnect(ar);                }                finally                {                    connectionWait.Close();                }#endif                if (!connectSuccess) throw new ConnectionSetupException("Timeout waiting for remoteEndPoint to accept TCP connection.");            }            catch (Exception ex)            {                CloseConnection(true, 17);                throw new ConnectionSetupException("Error during TCP connection establish with destination (" + ConnectionInfo + "). Destination may not be listening or connect timed out. " + ex.ToString());            }        }        /// <inheritdoc />        /// 开始监听进入的数据局        protected override void StartIncomingDataListen()        {            if (!NetworkComms.ConnectionExists(ConnectionInfo.RemoteIPEndPoint, ConnectionInfo.LocalIPEndPoint, ConnectionType.TCP, ConnectionInfo.ApplicationLayerProtocol))            {                CloseConnection(true, 18);                throw new ConnectionSetupException("A connection reference by endPoint should exist before starting an incoming data listener.");            }#if WINDOWS_PHONE            var stream = socket.InputStream.AsStreamForRead();            stream.BeginRead(dataBuffer, 0, dataBuffer.Length, new AsyncCallback(IncomingTCPPacketHandler), stream);   #elif NETFX_CORE            Task readTask = new Task(async () =>            {                                var buffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(dataBuffer);                var readBuffer = await socket.InputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.Partial);                                await IncomingTCPPacketHandler(readBuffer);            });                        readTask.Start();#else            lock (SyncRoot)            {                //以同步方式                if (NetworkComms.ConnectionListenModeUseSync)                {                    if (incomingDataListenThread == null)                    {                        //创建一个线程                        incomingDataListenThread = new Thread(IncomingTCPDataSyncWorker);                        //Incoming data always gets handled in a time critical fashion                        //设定数据处理的优先级                        incomingDataListenThread.Priority = NetworkComms.timeCriticalThreadPriority;                        incomingDataListenThread.Name = "UDP_IncomingDataListener";                        incomingDataListenThread.IsBackground = true;                        incomingDataListenThread.Start();                    }                }                //以异步方式处理                else                {                    if (asyncListenStarted) throw new ConnectionSetupException("Async listen already started. Why has this been called twice?.");                    asyncListenerInRead = true;                    //开始读取连接上的数据                    connectionStream.BeginRead(dataBuffer, 0, dataBuffer.Length, new AsyncCallback(IncomingTCPPacketHandler), connectionStream);                    asyncListenStarted = true;                }            }#endif            if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace("Listening for incoming data from " + ConnectionInfo);        }        /// <summary>        /// Asynchronous incoming connection data delegate        /// 以异步的方式处理连接上的数据        /// </summary>        /// <param name="ar">The call back state object</param> 回调状态对象#if NETFX_CORE        private async Task IncomingTCPPacketHandler(IBuffer buffer)#else        private void IncomingTCPPacketHandler(IAsyncResult ar)#endif        {            //Initialised with false so that logic still works in WP8            //初始化状态为false  所以可以在wp8系统下运行            bool dataAvailable = false;#if !WINDOWS_PHONE && !NETFX_CORE            //Incoming data always gets handled in a timeCritical fashion at this point            //Windows phone and RT platforms do not support thread priorities            //设定数据处理的优先级            //wp 和rt平台不支持线程优先级的设定            Thread.CurrentThread.Priority = NetworkComms.timeCriticalThreadPriority;#endif            try            {#if WINDOWS_PHONE                Stream stream = ar.AsyncState as Stream;                totalBytesRead = stream.EndRead(ar) + totalBytesRead;#elif NETFX_CORE                                buffer.CopyTo(0, dataBuffer, totalBytesRead, (int)buffer.Length);                totalBytesRead = (int)buffer.Length + totalBytesRead;                   #else                Stream stream;                if (SSLOptions.SSLEnabled)                    stream = (SslStream)ar.AsyncState;                else                    stream = (NetworkStream)ar.AsyncState;                if (!stream.CanRead)                    throw new ObjectDisposedException("Unable to read from stream.");                if (!asyncListenerInRead) throw new InvalidDataException("The asyncListenerInRead flag should be true. 1");                totalBytesRead = stream.EndRead(ar) + totalBytesRead;                asyncListenerInRead = false;                if (SSLOptions.SSLEnabled)                    //SSLstream does not have a DataAvailable property. We will just assume false.                    //SSLstream (安全套接层)数据流    不支持DataAvailable属性                       dataAvailable = false;                else                    dataAvailable = ((NetworkStream)stream).DataAvailable;#endif                if (totalBytesRead > 0)                {                    ConnectionInfo.UpdateLastTrafficTime();                    //If we have read a single byte which is 0 and we are not expecting other data                    //如果只读取到一个字节,内容为0 (猜测这样的单字节一般用于心跳检测)                    if (ConnectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled &&                         totalBytesRead == 1 && dataBuffer[0] == 0 && packetBuilder.TotalBytesExpected - packetBuilder.TotalBytesCached == 0)                    {                        if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... null packet removed in IncomingPacketHandler() from " + ConnectionInfo + ". 1");                    }                    else                    {                        if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... " + totalBytesRead.ToString() + " bytes added to packetBuilder for " + ConnectionInfo + ". Cached " + packetBuilder.TotalBytesCached.ToString() + " bytes, expecting " + packetBuilder.TotalBytesExpected.ToString() + " bytes.");                        //If there is more data to get then add it to the packets lists;                        //packetBuilder  数据包创建器                        //把读取到的字节添加到"数据包创建器"中                        //totalBytesRead  此次读取到的字节数量(int类型)   dataBuffer  (byte[] 字节数组)                        packetBuilder.AddPartialPacket(totalBytesRead, dataBuffer);#if !WINDOWS_PHONE && !NETFX_CORE                        //If we have more data we might as well continue reading synchronously                        //In order to deal with data as soon as we think we have sufficient we will leave this loop                        //如果我们有更多的数据 继续同步读取                        //如果接收到的数据足够多,将离开此循环                        //根据networkcomms的机制,第一个字节为数据包包头大小,系统会根据数据包包头大小解析出数据包包头,从数据包包头中读取数据包大小                        //这个数据包大小就是packetBuilder中totalBytesExpected,即期望的大小                        while (dataAvailable && packetBuilder.TotalBytesCached < packetBuilder.TotalBytesExpected)                        {                            int bufferOffset = 0;                            //We need a buffer for our incoming data                            //First we try to reuse a previous buffer                            //我们需要为进入的数据准备缓冲区                            //首先我们尝试使用以前的缓冲区                            if (packetBuilder.TotalPartialPacketCount > 0 && packetBuilder.NumUnusedBytesMostRecentPartialPacket() > 0)                                dataBuffer = packetBuilder.RemoveMostRecentPartialPacket(ref bufferOffset);                            else                            //If we have nothing to reuse we allocate a new buffer. As we are in this loop this can only be a suplementary buffer for THIS packet.                             //Therefore we choose a buffer size between the initial amount and the maximum amount based on the expected size                            //如果没有可重复使用的缓冲区,我们将新分配一个新的缓冲区                            //缓冲区的大小为  数据包创建器.期待的大小 减去  数据包创建器.已收到的大小  (即 数据包长度 减去  已经接收的长度)                            {                                long additionalBytesNeeded = packetBuilder.TotalBytesExpected - packetBuilder.TotalBytesCached;                                dataBuffer = new byte[Math.Max(Math.Min(additionalBytesNeeded, NetworkComms.MaxReceiveBufferSizeBytes), NetworkComms.InitialReceiveBufferSizeBytes)];                            }                            totalBytesRead = stream.Read(dataBuffer, bufferOffset, dataBuffer.Length - bufferOffset) + bufferOffset;                            if (totalBytesRead > 0)                            {                                ConnectionInfo.UpdateLastTrafficTime();                                //If we have read a single byte which is 0 and we are not expecting other data                                //处理单字节数据  一般为心跳消息                                if (ConnectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled && totalBytesRead == 1 && dataBuffer[0] == 0 && packetBuilder.TotalBytesExpected - packetBuilder.TotalBytesCached == 0)                                {                                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... null packet ignored in IncomingPacketHandler() from " + ConnectionInfo + ". 2");                                    //LastTrafficTime = DateTime.Now;                                }                                else                                {                                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... " + totalBytesRead.ToString() + " bytes added to packetBuilder for " + ConnectionInfo + ". Cached " + packetBuilder.TotalBytesCached.ToString() + " bytes, expecting " + packetBuilder.TotalBytesExpected.ToString() + " bytes.");                                    packetBuilder.AddPartialPacket(totalBytesRead, dataBuffer);                                                                        if (SSLOptions.SSLEnabled)                                                                                 //SSLstream does not have a DataAvailable property. We will just assume false.                                        //SSLstream 没有DataAvailable属性                                        dataAvailable = false;                                    else                                        dataAvailable = ((NetworkStream)stream).DataAvailable;                                }                            }                            else                                break;                        }#endif                    }                }                if (packetBuilder.TotalBytesCached > 0 && packetBuilder.TotalBytesCached >= packetBuilder.TotalBytesExpected)                {                    //Once we think we might have enough data we call the incoming packet handle hand off                    //Should we have a complete packet this method will start the appropriate task                    //This method will now clear byes from the incoming packets if we have received something complete.                    //一旦我们的数据包创建器(packetBuilder)中接收到足够一个数据包的数据,我们将会对数据进行处理                    //IncomingPacketHandleHandOff方法处理完packetBuilder中相应的数据后,会把已经处理完的数据删除掉                    IncomingPacketHandleHandOff(packetBuilder);                }                if (totalBytesRead == 0 && (!dataAvailable || ConnectionInfo.ConnectionState == ConnectionState.Shutdown))                    CloseConnection(false, -2);                else                {                    //We need a buffer for our incoming data                    //First we try to reuse a previous buffer                    //我们需要一个缓冲区来接收数据                    //我们先尝试使用以前的缓冲区                    if (packetBuilder.TotalPartialPacketCount > 0 && packetBuilder.NumUnusedBytesMostRecentPartialPacket() > 0)                        dataBuffer = packetBuilder.RemoveMostRecentPartialPacket(ref totalBytesRead);                    else                    {                        //If we have nothing to reuse we allocate a new buffer                        //If packetBuilder.TotalBytesExpected is 0 we know we‘re going to start waiting for a fresh packet. Therefore use the initial buffer size                        //如果没有可重复使用的缓冲区,我们将新分配一个新的缓冲区                        //如果 数据包创建器 期待的数据大小为0,我们将开始接收一个新的数据包的数据   此时 把缓冲区设置为初始大小                        if (packetBuilder.TotalBytesExpected == 0)                            dataBuffer = new byte[NetworkComms.InitialReceiveBufferSizeBytes];                        else                        //Otherwise this can only be a supplementary buffer for THIS packet. Therefore we choose a buffer size between the initial amount and the maximum amount based on the expected size                        //如果没有可重复使用的缓冲区,我们将新分配一个新的缓冲区                        //缓冲区的大小为  数据包创建器.期待的大小 减去  数据包创建器.已收到的大小  (即 数据包长度 减去  已经接收的长度)                        {                            long additionalBytesNeeded = packetBuilder.TotalBytesExpected - packetBuilder.TotalBytesCached;                            dataBuffer = new byte[Math.Max(Math.Min(additionalBytesNeeded, NetworkComms.MaxReceiveBufferSizeBytes), NetworkComms.InitialReceiveBufferSizeBytes)];                        }                        totalBytesRead = 0;                    }#if NETFX_CORE                    IBuffer newBuffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(dataBuffer);                    var task = IncomingTCPPacketHandler(await socket.InputStream.ReadAsync(newBuffer, newBuffer.Capacity - (uint)totalBytesRead, InputStreamOptions.Partial));#elif WINDOWS_PHONE                    stream.BeginRead(dataBuffer, totalBytesRead, dataBuffer.Length - totalBytesRead, IncomingTCPPacketHandler, stream);#else                    if (asyncListenerInRead) throw new InvalidDataException("The asyncListenerInRead flag should be false. 2");                    asyncListenerInRead = true;                    stream.BeginRead(dataBuffer, totalBytesRead, dataBuffer.Length - totalBytesRead, IncomingTCPPacketHandler, stream);#endif                }            }            catch (IOException)            {                CloseConnection(true, 12);            }            catch (ObjectDisposedException)            {                CloseConnection(true, 13);            }            catch (SocketException)            {                CloseConnection(true, 14);            }            catch (InvalidOperationException)            {                CloseConnection(true, 15);            }            catch (Exception ex)            {                LogTools.LogException(ex, "Error_TCPConnectionIncomingPacketHandler");                CloseConnection(true, 31);            }#if !WINDOWS_PHONE && !NETFX_CORE            Thread.CurrentThread.Priority = ThreadPriority.Normal;#endif        }#if !WINDOWS_PHONE && !NETFX_CORE        /// <summary>        /// Synchronous incoming connection data worker        /// 同步处理连接上进入的数据的处理器        /// </summary>        private void IncomingTCPDataSyncWorker()        {            bool dataAvailable = false;            try            {                while (true)                {                    if (ConnectionInfo.ConnectionState == ConnectionState.Shutdown)                        break;                    int bufferOffset = 0;                    //We need a buffer for our incoming data                    //First we try to reuse a previous buffer                    //我们需要为进入的数据准备缓冲区                    //首先我们尝试使用以前的缓冲区                    if (packetBuilder.TotalPartialPacketCount > 0 && packetBuilder.NumUnusedBytesMostRecentPartialPacket() > 0)                        dataBuffer = packetBuilder.RemoveMostRecentPartialPacket(ref bufferOffset);                    else                    {                        //If we have nothing to reuse we allocate a new buffer                        //If packetBuilder.TotalBytesExpected is 0 we know we‘re going to start waiting for a fresh packet. Therefore use the initial buffer size                        //如果没有可重复使用的缓冲区,我们将新分配一个新的缓冲区                        //如果 数据包创建器 期待的数据大小为0,我们将开始接收一个新的数据包的数据   此时 把缓冲区设置为初始大小                        if (packetBuilder.TotalBytesExpected == 0)                            dataBuffer = new byte[NetworkComms.InitialReceiveBufferSizeBytes];                        else                        //Otherwise this can only be a supplementary buffer for THIS packet. Therefore we choose a buffer size between the initial amount and the maximum amount based on the expected size                        //如果没有可重复使用的缓冲区,我们将新分配一个新的缓冲区                        //缓冲区的大小为  数据包创建器.期待的大小 减去  数据包创建器.已收到的大小  (即 数据包长度 减去  已经接收的长度)                        {                            long additionalBytesNeeded = packetBuilder.TotalBytesExpected - packetBuilder.TotalBytesCached;                            dataBuffer = new byte[Math.Max(Math.Min(additionalBytesNeeded, NetworkComms.MaxReceiveBufferSizeBytes), NetworkComms.InitialReceiveBufferSizeBytes)];                        }                    }                    //We block here until there is data to read                    //When we read data we read until method returns or we fill the buffer length                    //程序将会阻塞  直到读取到数据                    //我们读取数据 直到方法返回或者读取到缓冲区大小的数据                    totalBytesRead = connectionStream.Read(dataBuffer, bufferOffset, dataBuffer.Length - bufferOffset) + bufferOffset;                    //Check to see if there is more data ready to be read                    //检查是否还有数据需要读取                    if (SSLOptions.SSLEnabled)                        //SSLstream does not have a DataAvailable property. We will just assume false.                        //SSLStream没有DataAvailable属性                        dataAvailable = false;                    else                        dataAvailable = ((NetworkStream)connectionStream).DataAvailable;                    //If we read any data it gets handed off to the packetBuilder                    //如果我们读取到数据,交给packetBuilder处理                    if (totalBytesRead > 0)                    {                        ConnectionInfo.UpdateLastTrafficTime();                        //If we have read a single byte which is 0 and we are not expecting other data                        //处理单字节 内容为0 的数据  (一般为心跳检测)                        if (ConnectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Enabled && totalBytesRead == 1 && dataBuffer[0] == 0 && packetBuilder.TotalBytesExpected - packetBuilder.TotalBytesCached == 0)                        {                            if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... null packet removed in IncomingDataSyncWorker() from "+ConnectionInfo+".");                        }                        else                        {                            if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... " + totalBytesRead.ToString() + " bytes added to packetBuilder for " + ConnectionInfo + ". Cached " + packetBuilder.TotalBytesCached.ToString() + " bytes, expecting " + packetBuilder.TotalBytesExpected.ToString() + " bytes.");                            //添加数据到 数据包创建器中                            packetBuilder.AddPartialPacket(totalBytesRead, dataBuffer);                        }                    }                    else if (totalBytesRead == 0 && (!dataAvailable || ConnectionInfo.ConnectionState == ConnectionState.Shutdown))                    {                        //If we read 0 bytes and there is no data available we should be shutting down                        //如果我们没有读取到数据 应该关闭连接                        CloseConnection(false, -10);                        break;                    }                    //If we have read some data and we have more or equal what was expected we attempt a data hand off                    //如果我们读取到足够的数据(可以解析出一个数据包),对数据进行处理                    if (packetBuilder.TotalBytesCached > 0 && packetBuilder.TotalBytesCached >= packetBuilder.TotalBytesExpected)                        IncomingPacketHandleHandOff(packetBuilder);                }            }            //On any error here we close the connection            //捕捉异常  关闭连接            catch (NullReferenceException)            {                CloseConnection(true, 7);            }            catch (IOException)            {                CloseConnection(true, 8);            }            catch (ObjectDisposedException)            {                CloseConnection(true, 9);            }            catch (SocketException)            {                CloseConnection(true, 10);            }            catch (InvalidOperationException)            {                CloseConnection(true, 11);            }            catch (Exception ex)            {                LogTools.LogException(ex, "Error_TCPConnectionIncomingPacketHandler");                CloseConnection(true, 39);            }            //Clear the listen thread object because the thread is about to end            //清除监听线程 因为线程将关闭            incomingDataListenThread = null;            if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace("Incoming data listen thread ending for " + ConnectionInfo);        }        /// <summary>        /// Configure the SSL stream from this connection        /// 配置当期连接上 SSL 数据流        /// </summary>        private void ConfigureSSLStream()        {            try            {                if (ConnectionInfo.ServerSide)                {                    connectionStream = new SslStream(tcpClient.GetStream(), false,                        new RemoteCertificateValidationCallback(CertificateValidationCallback),                        new LocalCertificateSelectionCallback(CertificateSelectionCallback));                    ((SslStream)connectionStream).AuthenticateAsServer(SSLOptions.Certificate, SSLOptions.RequireMutualAuthentication, SslProtocols.Default, false);                }                else                {                    X509CertificateCollection certs = new X509CertificateCollection();                    if (SSLOptions.Certificate != null) certs.Add(SSLOptions.Certificate);                    //If we have a certificate set we use that to authenticate                    connectionStream = new SslStream(tcpClient.GetStream(), false,                        new RemoteCertificateValidationCallback(CertificateValidationCallback),                        new LocalCertificateSelectionCallback(CertificateSelectionCallback));                    ((SslStream)connectionStream).AuthenticateAsClient(SSLOptions.CertificateName, certs, SslProtocols.Default, false);                }            }            catch (AuthenticationException ex)            {                throw new ConnectionSetupException("SSL authentication failed. Please check configuration and try again.", ex);            }            SSLOptions.Authenticated = true;        }        /// <summary>        /// Callback used to determine if the provided certificate should be accepted        /// 回调方法 用于确定是否应该接受所提供的证书        /// </summary>        /// <param name="sender"></param>        /// <param name="certificate"></param>        /// <param name="chain"></param>        /// <param name="sslPolicyErrors"></param>        /// <returns></returns>        private bool CertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)        {            if (sslPolicyErrors == SslPolicyErrors.None)                return true;            else if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNotAvailable && ConnectionInfo.ServerSide)                //If the client did not provide a remote certificate it may well be because                //we were not requesting one                //如果客户没有提供远程认证它很可能是因为我们没有要求                return !SSLOptions.RequireMutualAuthentication;            else if (SSLOptions.AllowSelfSignedCertificate && //If we allows self signed certificates we make sure the errors are correct  如果我们允许自签名认证 我们确定这些错误是正确的                chain.ChainStatus.Length == 1 && //Only a single chain error 只是一个单一的链错误                sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors &&                chain.ChainStatus[0].Status == X509ChainStatusFlags.UntrustedRoot)            {                //If we have a local certificate we compare them  如果我们有一个本地的证书 我们比较他们                if (SSLOptions.Certificate != null)                    return certificate.Equals(SSLOptions.Certificate);                else                    return true;            }            else                return false;        }        /// <summary>        /// Certificate selection callback        /// 证书选择 回调方法        /// </summary>        /// <param name="sender"></param>        /// <param name="targetHost"></param>        /// <param name="localCertificates"></param>        /// <param name="remoteCertificate"></param>        /// <param name="acceptableIssuers"></param>        /// <returns></returns>        private X509Certificate CertificateSelectionCallback(object sender, string targetHost, X509CertificateCollection localCertificates,             X509Certificate remoteCertificate, string[] acceptableIssuers)        {            return SSLOptions.Certificate;        }#endif        /// <inheritdoc />        protected override void CloseConnectionSpecific(bool closeDueToError, int logLocation = 0)        {#if WINDOWS_PHONE || NETFX_CORE            //Try to close the socket            try            {                socket.Dispose();            }            catch (Exception)            {            }#else            //The following attempts to correctly close the connection            //Try to close the networkStream first            //以下试图正确的关闭连接            //首先尝试关闭网络流            try            {                if (connectionStream != null) connectionStream.Close();            }            catch (Exception)            {            }            finally            {                connectionStream = null;            }            //Try to close the tcpClient            //尝试关闭tcpClient对象            try            {                if (tcpClient.Client!=null)                {                    tcpClient.Client.Disconnect(false);#if !ANDROID                    //Throws uncatchable exception in android                    //在安卓系统中抛出不可捕捉的异常                    tcpClient.Client.Close();#endif                }            }            catch (Exception)            {            }            //Try to close the tcpClient            //尝试关闭连接            try            {#if !ANDROID                //Throws uncatchable exception in android                //在安卓系统中抛出不可捕捉的异常                tcpClient.Close();#endif            }            catch (Exception)            {            }#endif        }        /// <inheritdoc />        protected override double[] SendStreams(StreamTools.StreamSendWrapper[] streamsToSend, double maxSendTimePerKB, long totalBytesToSend)        {            double[] timings = new double[streamsToSend.Length];            Stream sendingStream;#if WINDOWS_PHONE || NETFX_CORE            sendingStream = socket.OutputStream.AsStreamForWrite();#else            sendingStream = connectionStream;#endif            for(int i=0; i<streamsToSend.Length; i++)            {                if (streamsToSend[i].Length > 0)                {                    //Write each stream                    //写入数据流                    timings[i] = streamsToSend[i].ThreadSafeStream.CopyTo(sendingStream, streamsToSend[i].Start, streamsToSend[i].Length, NetworkComms.SendBufferSizeBytes, maxSendTimePerKB, MinSendTimeoutMS);                    streamsToSend[i].ThreadSafeStream.Dispose();                }                else                    timings[i] = 0;            }#if WINDOWS_PHONE || NETFX_CORE            sendingStream.Flush();#endif#if !WINDOWS_PHONE && !NETFX_CORE            if (!tcpClient.Connected)            {                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Error("TCPClient is not marked as connected after write to networkStream. Possibly indicates a dropped connection.");                                throw new CommunicationException("TCPClient is not marked as connected after write to networkStream. Possibly indicates a dropped connection.");            }#endif            return timings;        }    }

 

介绍开源的.net通信框架NetworkComms框架 源码分析(二十三 )TCPConnection