异步服务器端的代码。

代码

class AsynchronousIoServer
{
    private Socket _serverSocket;
    private int _port;
    public AsynchronousIoServer(int port_num)
    {
        _port = port_num;
    }
    private class ConnectionInfo
    {
        public Socket Socket;
        public byte[] Buffer;
    }
    private List<ConnectionInfo> _connections =
    new List<ConnectionInfo>();
    public void Start()
    {
        SetupServerSocket();
        for (int i = 0; i < 10; i++)
            _serverSocket.BeginAccept(
            new AsyncCallback(AcceptCallback), _serverSocket);
    }
    private void SetupServerSocket()
    {
        IPHostEntry localMachineInfo =
        Dns.GetHostEntry(Dns.GetHostName());
        IPEndPoint myEndpoint = new IPEndPoint(
        localMachineInfo.AddressList[0], _port);
        _serverSocket = new Socket(myEndpoint.Address.AddressFamily,
        SocketType.Stream, ProtocolType.Tcp);
        _serverSocket.Bind(myEndpoint);
        _serverSocket.Listen((int)SocketOptionName.MaxConnections);
    }
    private void AcceptCallback(IAsyncResult result)
    {
        ConnectionInfo connection = new ConnectionInfo();
        try
        {
            Socket s = (Socket)result.AsyncState;
            connection.Socket = s.EndAccept(result);
            connection.Buffer = new byte[255];
            lock (_connections) _connections.Add(connection);
            connection.Socket.BeginReceive(connection.Buffer, 0,
            connection.Buffer.Length, SocketFlags.None,
            new AsyncCallback(ReceiveCallback), connection);
            _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback),
            result.AsyncState);
        }
        catch (SocketException exc)
        {
            CloseConnection(connection);
            Console.WriteLine("Socket exception: " + exc.SocketErrorCode);
        }
        catch (Exception exc)
        {
            CloseConnection(connection);
            Console.WriteLine("Exception: " + exc);
        }
    }
    private void ReceiveCallback(IAsyncResult result)
    {
        ConnectionInfo connection = (ConnectionInfo)result.AsyncState;
        try
        {
            int bytesRead = connection.Socket.EndReceive(result);
            if (0 != bytesRead)
            {
                lock (_connections)
                {
                    foreach (ConnectionInfo conn in _connections)
                    {
                        if (connection != conn)
                        {
                            conn.Socket.Send(connection.Buffer, bytesRead,
                            SocketFlags.None);
                        }
                    }
                }
                connection.Socket.BeginReceive(connection.Buffer, 0,
                connection.Buffer.Length, SocketFlags.None,
                new AsyncCallback(ReceiveCallback), connection);
            }
            else CloseConnection(connection);
        }
        catch (SocketException exc)
        {
            CloseConnection(connection);
            Console.WriteLine("Socket exception: " + exc.SocketErrorCode);
        }
        catch (Exception exc)
        {
            CloseConnection(connection);
            Console.WriteLine("Exception: " + exc);
        }
    }
    private void CloseConnection(ConnectionInfo ci)
    {
        ci.Socket.Close();
        lock (_connections) _connections.Remove(ci);
    }
}

socket客户端程序

  服务器端已经反应灵敏,承载量也很大,现在需要一个高效的客户端程序。相比较而言,这个就相对简单了。在客户端程序里,首先要构造一个socket。可以选择让该socket与特定的地址和端口绑定;如果没有绑定的话,网络层就会提供一个它认为最好的地址与其绑定,同时还有一个特定的端口,这个端口号在1024到5000之间。

之所以需要绑定客户端程序的socket到一定的地址和端口,是因为,在一个有多个网卡的电脑终端上,而且每个网卡的地址不同,此时就可以选择客户端所要使用的网卡。

接下来就要使用socket连接服务器端。连接也可以采用同步或者异步的方式。当你需要连接到多个服务器端的时候,异步是非常有用的方法。每个socket不必等待前面的socket连接建立完成,程序可以同时开始多个连接。

  即使服务器端可用,使用客户端连接的时候依然有可能遇到WSAECONNREFUSED 的错误,这在服务器端的队列已满的情况下有可能发生。在这种情况下,需要客户端每个一定时间尝试重新连接。

更过的改进

  第一个方面是接收连接。有三种基本接受异步连接的方法:只接收连接,接收连接并接收连接发送的前几个字节的数据,用特殊提供的socket接收连接并接收连接发送的前几个字节的数据。.NET框架1.x版本里只能使用第一种方法,而在.NET2.0里面,三个方法都可以适用。

  前面的服务器端的代码使用的第一种异步方法。只接收连接的好处在于可以将接收逻辑和消息处理逻辑隔离开来。这是一个非常简单的编程模型,但是并不能提供最好的性能。

接收连接并且接收数据方法的好处在于对第一个消息处理的性能的显著提升,这主要因为基本上不需要调用核心处理程序。当使用特定协议,并已知协议头的情况下,这种方法非常好。不好的地方在于只有数据接受完毕后采用调用BeginAccept 的处理函数,这可能产生一些程序根本都不知所以的连接。该方法与.NET2.0里面的Socket.Disconnect 方法相结合后有了很大优势。在以前的socket程序中,如果socket用不到了,就需要关闭并且删除该实例。有了Socket.Disconnect方法,你就可以重用该实例,这是通过程序本身的一个socket实例池实现的。在某些方案里面采用这种控制的话会导致性能的极大提升。

  程序运行时,首先告诉操作系统监听连接,它就会保持一个特定长度的连接队列。假定最大数目为200,那就意味着如果有超过200个客户端同时连接时,队列之外的客户端会因为服务器端的拒接而发生WSAECONNREFUSED 错误。解决该问题的一个方案是使用多个接收处理。使用该方法就可以不断从排队连接里面接收处理连接,就算就在处理的连接正在处理尚未提交接收请求。这就大大增多了监听队列的厚度。

  尽管如此,多异步操作是有代价的。连接处理增多就会导致性能的下降,而承载量的增大也是以性能的下降为代价的。

转载于:https://www.cnblogs.com/gleamy_ming/archive/2010/07/16/1778635.html

[转载].NET中高效能的socket编程相关推荐

  1. Linux的SOCKET编程详解——非常叼

    http://blog.csdn.net/hguisu/article/details/7445768/ 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] Linux的SOCKE ...

  2. Android应用开发提高篇(4)-----Socket编程(多线程、双向通信)(转载)

    转自:http://www.cnblogs.com/lknlfy/archive/2012/03/04/2379628.html 一.概述 关于Socket编程的基本方法在基础篇里已经讲过,今天把它给 ...

  3. (转载)Socket编程基本流程实践

    Socket编程基本流程实践 通讯基本流程图如下所示: Server端代码(ServerDemo.cpp): 1 #include <WinSock2.h> 2 #include < ...

  4. Linux的SOCKET编程详解(转载)

    一. 网络中进程之间如何通信 进程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进程之间既互不干扰又协调一致工作,操作系统为进程通信提供了相应设施,如: UN ...

  5. Windows Socket编程笔记之最简单的小Demo

    Windows Socket编程的大致过程: 服务器端: ----过程-------------对应的API-------  0.初始化         |  WSAStartup()  1.创建So ...

  6. [Python_7] Python Socket 编程

    0. 说明 Python Socket 编程 1. TCP 协议 [TCP Server] 通过 netstat -ano 查看端口是否开启 # -*-coding:utf-8-*-"&qu ...

  7. C# Socket编程(5)使用TCP Socket

    TCP 协议(Transmission Control Protocol,传输控制协议)是TCP/IP体系中面向连接(connection oriented)的传输层(transport layer) ...

  8. socket编程缓冲区大小对send()的影响

    1. 概述 Socket编程中,使用send()传送数据时,返回结果受到以下几个因素的影响: • Blocking模式或non-blocking模式 • 发送缓冲区的大小 • 接收窗口大小 本文档介绍 ...

  9. C# socket编程实践——支持广播的简单socket服务器

    在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# socket编程基本知识,写一个支持广播的简单server/clie ...

最新文章

  1. 感知机算法分类原理学习笔记
  2. 004-什么是软件测试?软件测试的目的与原则
  3. 交换排序 java_java实现交换排序
  4. ModelAndView介绍
  5. zookeeper 原理
  6. terminal mysql 停止_转载MySQL之终端(Terminal)管理MySQL
  7. Python类对象的运算符add重载
  8. android 动态设置priority,Android属性之android:priority
  9. 基于TensorFlow实现自定义层的项目代码
  10. 拼多多上市关你什么事?
  11. 揭秘黑客攻击内幕和20个黑客相关术语
  12. php居中显示代码,css居中代码是什么
  13. matlab分离实部虚部,MATLAB/simulink中,想让电流表测出的值为复数形式,有实部虚部,将powergui设置为phasors仿真,总是出错...
  14. 什么是SRE?SRE需要具备什么能力?
  15. 屏幕种类有哪些,特点,怎么挑?TFT、LCD、OLED、IPS、TN的含义与区别?高色域、刷新率、广视角、雾面屏又是什么?
  16. 路径跟踪与轨迹跟踪概念
  17. android wifi无法连接手机号码,安卓手机无法使用WiFi连接ApowerMirror解决方法
  18. WIN32下实现输入法所需要的一些必要消息、函数和说明
  19. Fatal error
  20. 我和python的第一次亲密接触

热门文章

  1. Android中获取系统语言(适用于Android7.0以上系统)
  2. MySQL双主配置步骤
  3. error 图片,加载错误-》实用笔记
  4. SpringCloud配置中心-Config
  5. SSM项目的数据库密码加密方案
  6. 当安卓 Emoji 遇上苹果 Emoji:傻傻分不清楚
  7. 浅谈ES6原生Promise
  8. linux网络命令1
  9. META的SEO优化中方法技巧
  10. 以佛像喷泉来探讨BCH物联网应用潜力