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

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

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

TCP连接监听器

 /// <summary>
    /// A TCP connection listener
    /// TCP连接监听器
    /// </summary>
    public class TCPConnectionListener : ConnectionListenerBase
    {
#if WINDOWS_PHONE || NETFX_CORE
        /// <summary>
        /// The equivalent TCPListener class in windows phone
        /// WP系统中与TCPListener类相对应的类
        /// </summary>
        StreamSocketListener listenerInstance;
#else
        /// <summary>
        /// The .net TCPListener class.
        /// .net中TCPListener类
        /// </summary>
        TcpListener listenerInstance;

        /// <summary>
        /// SSL options that are associated with this listener
        /// 监听器相对应的SSL选项
        /// </summary>
        public SSLOptions SSLOptions { get; private set; }
#endif

        /// <summary>
        /// Create a new instance of a TCP listener
        /// 创建一个新的TCP监听器实例
        /// </summary>
        /// <param name="sendReceiveOptions">The SendReceiveOptions to use with incoming data on this listener  此监听器上接收进入的数据所使用的收发参数 </param>
        /// <param name="applicationLayerProtocol">If enabled NetworkComms.Net uses a custom
        /// application layer protocol to provide useful features such as inline serialisation,
        /// transparent packet transmission, remote peer handshake and information etc. We strongly
        /// recommend you enable the NetworkComms.Net application layer protocol.</param>
        /// applicationLayerProtocol 应用层协议状态  我们强烈建议您启用此项,使得networkcomms能为您提供内部序列化,透明数据包传送,远程端点握手等功能。
        /// 只有与其他语言进行通信时,此项才设置为禁用
        /// <param name="allowDiscoverable">Determines if the newly created <see cref="ConnectionListenerBase"/> will be discoverable if <see cref="Tools.PeerDiscovery"/> is enabled.</param>
        /// allowDiscoverable  是否允许被发现  此项与networkcomms中一项端点自动扫描功能有关
        public TCPConnectionListener(SendReceiveOptions sendReceiveOptions,
            ApplicationLayerProtocolStatus applicationLayerProtocol, bool allowDiscoverable = false)
            :base(ConnectionType.TCP, sendReceiveOptions, applicationLayerProtocol, allowDiscoverable)
        {
#if !WINDOWS_PHONE && !NETFX_CORE
            SSLOptions = new SSLOptions();
#endif
        }

#if !WINDOWS_PHONE && !NETFX_CORE
        /// <summary>
        /// Create a new instance of a TCP listener
        /// 创建一个新的TCP监听器实例
        /// </summary>
        /// <param name="sendReceiveOptions">The SendReceiveOptions to use with incoming data on this listener  此监听器上接收进入的数据所使用的收发参数 </param>
        /// <param name="applicationLayerProtocol">If enabled NetworkComms.Net uses a custom
        /// application layer protocol to provide useful features such as inline serialisation,
        /// transparent packet transmission, remote peer handshake and information etc. We strongly
        /// recommend you enable the NetworkComms.Net application layer protocol.</param>
        /// applicationLayerProtocol 应用层协议状态  我们强烈建议您启用此项,使得networkcomms能为您提供内部序列化,透明数据包传送,远程端点握手等功能。
        /// 只有与其他语言进行通信时,此项才设置为禁用
        /// <param name="allowDiscoverable">Determines if the newly created <see cref="ConnectionListenerBase"/> will be discoverable if <see cref="Tools.PeerDiscovery"/> is enabled.</param>
        /// allowDiscoverable  是否允许被发现  此项与networkcomms中一项端点自动扫描功能有关
        public TCPConnectionListener(SendReceiveOptions sendReceiveOptions,
            ApplicationLayerProtocolStatus applicationLayerProtocol, SSLOptions sslOptions, bool allowDiscoverable = false)
            : base(ConnectionType.TCP, sendReceiveOptions, applicationLayerProtocol, allowDiscoverable)
        {
            this.SSLOptions = sslOptions;
        }
#endif

        /// <inheritdoc />
        internal override void StartListening(EndPoint desiredLocalListenEndPoint, bool useRandomPortFailOver)
        {
            if (desiredLocalListenEndPoint.GetType() != typeof(IPEndPoint)) throw new ArgumentException("Invalid desiredLocalListenEndPoint type provided.", "desiredLocalListenEndPoint");
            if (IsListening) throw new InvalidOperationException("Attempted to call StartListening when already listening.");

            IPEndPoint desiredLocalListenIPEndPoint = (IPEndPoint)desiredLocalListenEndPoint;

            try
            {
#if WINDOWS_PHONE || NETFX_CORE
                listenerInstance = new StreamSocketListener();
                listenerInstance.ConnectionReceived += newListenerInstance_ConnectionReceived;
                listenerInstance.BindEndpointAsync(new Windows.Networking.HostName(desiredLocalListenIPEndPoint.Address.ToString()), desiredLocalListenIPEndPoint.Port.ToString()).AsTask().Wait();
#else
                listenerInstance = new TcpListener(desiredLocalListenIPEndPoint);
                listenerInstance.Start();
                listenerInstance.BeginAcceptTcpClient(TCPConnectionReceivedAsync, null);
#endif
            }
            catch (SocketException)
            {
                //If the port we wanted is not available
                //如果我们希望监听的端口已经被占用  useRandomPortFailOver(是否随机指定一个新端口)
                if (useRandomPortFailOver)
                {
                    try
                    {
#if WINDOWS_PHONE || NETFX_CORE
                        listenerInstance.BindEndpointAsync(new Windows.Networking.HostName(desiredLocalListenIPEndPoint.Address.ToString()), "").AsTask().Wait();
#else
                        listenerInstance = );
                        listenerInstance.Start();
                        listenerInstance.BeginAcceptTcpClient(TCPConnectionReceivedAsync, null);
#endif
                    }
                    catch (SocketException)
                    {
                        //If we get another socket exception this appears to be a bad IP. We will just ignore this IP
                        //如果我们重新指定端口,还是没有监听成功,则可能是IP地址的问题
                        if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Error("It was not possible to open a random port on " + desiredLocalListenIPEndPoint.Address + ". This endPoint may not support listening or possibly try again using a different port.");
                        throw new CommsSetupShutdownException("It was not possible to open a random port on " + desiredLocalListenIPEndPoint.Address + ". This endPoint may not support listening or possibly try again using a different port.");
                    }
                }
                else
                {
                    if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Error("It was not possible to open port #" + desiredLocalListenIPEndPoint.Port.ToString() + " on " + desiredLocalListenIPEndPoint.Address + ". This endPoint may not support listening or possibly try again using a different port.");
                    throw new CommsSetupShutdownException("It was not possible to open port #" + desiredLocalListenIPEndPoint.Port.ToString() + " on " + desiredLocalListenIPEndPoint.Address + ". This endPoint may not support listening or possibly try again using a different port.");
                }
            }

#if WINDOWS_PHONE || NETFX_CORE
            this.LocalListenEndPoint = new IPEndPoint(desiredLocalListenIPEndPoint.Address, int.Parse(listenerInstance.Information.LocalPort));
#else
            this.LocalListenEndPoint = (IPEndPoint)listenerInstance.LocalEndpoint;
#endif
            this.IsListening = true;
        }

        /// <inheritdoc />
        internal override void StopListening()
        {
            IsListening = false;

            try
            {
#if WINDOWS_PHONE || NETFX_CORE
                listenerInstance.Dispose();
#else
                listenerInstance.Stop();
#endif
            }
            catch (Exception) { }
        }

#if WINDOWS_PHONE || NETFX_CORE
        private void newListenerInstance_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        {
            try
            {
                IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(args.Socket.Information.LocalAddress.DisplayName.ToString()), int.Parse(args.Socket.Information.LocalPort));
                IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(args.Socket.Information.RemoteAddress.DisplayName.ToString()), int.Parse(args.Socket.Information.RemotePort));

                ConnectionInfo newConnectionInfo = new ConnectionInfo(ConnectionType.TCP, remoteEndPoint, localEndPoint, ApplicationLayerProtocol, this);
                TCPConnection.GetConnection(newConnectionInfo, NetworkComms.DefaultSendReceiveOptions, args.Socket, true);
            }
            catch (ConfirmationTimeoutException)
            {
                //If this exception gets thrown its generally just a client closing a connection almost immediately after creation
            }
            catch (CommunicationException)
            {
                //If this exception gets thrown its generally just a client closing a connection almost immediately after creation
            }
            catch (ConnectionSetupException)
            {
                //If we are the server end and we did not pick the incoming connection up then tooo bad!
            }
            catch (SocketException)
            {
                //If this exception gets thrown its generally just a client closing a connection almost immediately after creation
            }
            catch (Exception ex)
            {
                //For some odd reason SocketExceptions don't always get caught above, so another check
                if (ex.GetBaseException().GetType() != typeof(SocketException))
                {
                    //Can we catch the socketException by looking at the string error text?
                    if (ex.ToString().StartsWith("System.Net.Sockets.SocketException"))
                        LogTools.LogException(ex, "ConnectionSetupError_SE");
                    else
                        LogTools.LogException(ex, "ConnectionSetupError");
                }
            }
        }
#else
        /// <summary>
        /// Async method for handling up new incoming TCP connections
        /// 处理新的TCP连接的异步方法
        /// </summary>
        private void TCPConnectionReceivedAsync(IAsyncResult ar)
        {
            if (!IsListening)
                return;

            try
            {
                TcpClient newTCPClient = listenerInstance.EndAcceptTcpClient(ar);
                ConnectionInfo newConnectionInfo = new ConnectionInfo(ConnectionType.TCP, (IPEndPoint)newTCPClient.Client.RemoteEndPoint, (IPEndPoint)newTCPClient.Client.LocalEndPoint, ApplicationLayerProtocol, this);

                if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Info("New incoming TCP connection from " + newConnectionInfo);

                //We have to use our own thread pool here as the performance of the .Net one is awful
                //此处我们使用了networkcomms自带的自定义线程池  其性能超越了.net自带的线程池
                NetworkComms.IncomingConnectionEstablishThreadPool.EnqueueItem(QueueItemPriority.Normal, new WaitCallback((obj) =>
                {
                    #region Pickup The New Connection
                    try
                    {
                        TCPConnection.GetConnection(newConnectionInfo, ListenerDefaultSendReceiveOptions, newTCPClient, true, SSLOptions);
                    }
                    catch (ConfirmationTimeoutException)
                    {
                        //If this exception gets thrown its generally just a client closing a connection almost immediately after creation
                        //如果此处抛出异常  一般为客户端创建连接后立即关闭了连接
                    }
                    catch (CommunicationException)
                    {
                        //If this exception gets thrown its generally just a client closing a connection almost immediately after creation
                        // //如果此处抛出异常  一般为客户端创建连接后立即关闭了连接
                    }
                    catch (ConnectionSetupException)
                    {
                        //If we are the server end and we did not pick the incoming connection up then tooo bad!
                        //如果我们是服务器端 我们没有接收到进入的连接
                    }
                    catch (SocketException)
                    {
                        //If this exception gets thrown its generally just a client closing a connection almost immediately after creation
                        // //如果此处抛出异常  一般为客户端创建连接后立即关闭了连接
                    }
                    catch (Exception ex)
                    {
                        //For some odd reason SocketExceptions don't always get caught above, so another check
                        //由于一些未知的原因  上面的代码不能捕捉到所有的异常  所以我们还要尽行一些检测
                        if (ex.GetBaseException().GetType() != typeof(SocketException))
                        {
                            //Can we catch the socketException by looking at the string error text?
                            //通过检测字符型错误信息来捕捉 socket异常
                            if (ex.ToString().StartsWith("System.Net.Sockets.SocketException"))
                                LogTools.LogException(ex, "ConnectionSetupError_SE");
                            else
                                LogTools.LogException(ex, "ConnectionSetupError");
                        }
                    }
                    #endregion
                }), null);
            }
            catch (SocketException)
            {
                //如果此处抛出异常  一般为客户端创建连接后立即关闭了连接
            }
            catch (Exception ex)
            {
                //For some odd reason SocketExceptions don't always get caught above, so another check
                //由于一些未知的原因  上面的代码不能捕捉到所有的异常   所以我们还要尽行一些检测
                if (ex.GetBaseException().GetType() != typeof(SocketException))
                {
                    //Can we catch the socketException by looking at the string error text?
                    if (ex.ToString().StartsWith("System.Net.Sockets.SocketException"))
                        LogTools.LogException(ex, "ConnectionSetupError_SE");
                    else
                        LogTools.LogException(ex, "ConnectionSetupError");
                }
            }
            finally
            {
                listenerInstance.BeginAcceptTcpClient(TCPConnectionReceivedAsync, null);
            }
        }
#endif
    }

介绍开源的.net通信框架NetworkComms框架 源码分析(二十一 )TCPConnectionListener的更多相关文章

  1. DotNetty网络通信框架学习之源码分析

    DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...

  2. 框架-springmvc源码分析(二)

    框架-springmvc源码分析(二) 参考: http://www.cnblogs.com/leftthen/p/5207787.html http://www.cnblogs.com/leftth ...

  3. 深入理解分布式调度框架TBSchedule及源码分析

    简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...

  4. 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)

    1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...

  5. 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)

    1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e,  要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...

  6. $Django cbv源码分析 djangorestframework框架之APIView源码分析

    1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...

  7. ABP源码分析二十六:核心框架中的一些其他功能

    本文是ABP核心项目源码分析的最后一篇,介绍一些前面遗漏的功能 AbpSession AbpSession: 目前这个和CLR的Session没有什么直接的联系.当然可以自定义的去实现IAbpSess ...

  8. ④NuPlayer播放框架之Renderer源码分析

    [时间:2016-11] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,渲染器,render] 0 导读 之前我们分析了NuPlayer的实现代码,本文将重点聚 ...

  9. ⑤NuPlayer播放框架之GenericSource源码分析

    [时间:2017-01] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,GenericSource] 0 导读 GenericSource是NuPlayer:: ...

  10. ③NuPlayer播放框架之类NuPlayer源码分析

    [时间:2016-10] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架] 0 引言 差不多一个月了,继续分析AOSP的播放框架的源码.这次我们需要深入分析的是N ...

随机推荐

  1. servlet到底是什么?

    Servlet(Server Applet),全称Java Servlet,是用Java编写的服务器端程序.指任何实现了这个Servlet接口的类或者实现Servlet接口的类,当然或者实现接口继承方 ...

  2. Logstash为什么那么慢?—— json序列化

    今天跟峡谷金桥聊天,询问起Logstash的性能,金桥提示说Logstash中json的序列化是浪费性能的一方面.于是便有了下面的测试: 第一步,造数据 首先需要造一份数据,数据可以通过logstas ...

  3. Java程序员的日常 —— 响应式导航Demo

    这两天想要做响应式的页面,于是本着重复造轮子的想法,模仿Bootstrap官网,精简了一个响应式导航的Demo. 效果 代码 <!DOCTYPE html> <html> &l ...

  4. WPF入门教程系列一——基础

    一. 前言   最近在学习WPF,学习WPF首先上的是微软的MSDN,然后再搜索了一下网络有关WPF的学习资料.为了温故而知新把学习过程记录下来,以备后查.这篇主要讲WPF的开发基础,介绍了如何使用V ...

  5. LigerUI Tree

    <!DOCTYPE html> <%@ page language="java" contentType="text/html; charset=utf ...

  6. .NET程序集强命名删除与再签名技术 源代码剖析

    如果你想去除一个程序集的强签名(strong name),目前为止可以有两个途径 1  反编译为IL代码,删除签名部分,再编译为程序集 2  应用Re-Sign程序,直接对一个程序集再签名 生成和读取 ...

  7. OOCSS入门学习

    对于面向对象大家肯定都有多多少少的了解,这里所说的OOCSS就是说面向对象的CSS,得说明的是OOCSS并不是一门新语言也不是什么库,而是一种概念和javascript面向对象一样. 可能你这样写过C ...

  8. 用命令行编译java并生成可执行的jar包

    用命令行编译java并生成可执行的jar包 1.编写源代码. 编写源文件:CardLayoutDemo.java并保存,例如:I:\myApp\CardLayoutDemo.java.程序结构如下: ...

  9. poj 2385Apple Catching(简单dp)

    /* 题意: 有两棵苹果树,每一棵苹果树每一秒间隔的掉落下来一个苹果,一个人在树下接住苹果,不让苹果掉落! 人在两棵树之间的移动是很快的!但是这个人移动的次数是有限制的,问最多可以接住多少个苹果! 思 ...

  10. vs切换当前编辑文件时自动定位目录树

    在编辑区,切换当前编辑文件时(单击.cpp或.h文件选项卡),"解决方案资源管理器"目录树会自动定位当前编辑的文件,并以灰色标识,当一个解决方案中的工程数目数目很多,每个工程下面又 ...