zoukankan      html  css  js  c++  java
  • <转载>.NET Socket开发之异步Socket

    在基于.NET的网络服务端的开发中,我们用到和听到的最多的恐怕就是异步Socket了。异步Socket的性能比同步高出很多,但是编写代码比较复杂。因此异步Socket也是网络上讨论比较多的话题。
     
    今天,我们就来讨论一下如何用异步Socket开发网络应用。在此之前我们先讨论两个问题。
     
    一、异步Socket是如何工作的:
     
    那异步Socket是如何工作的呢?我以接收一条消息来说明这个问题。首先,程序向系统投递一个接收数据的请求,并为其指定一个数据缓冲区和回调函数,回调函数用来指示当数据到达后将如何处理,然后我们的程序继续执行下去,当有数据到达的时候,系统将数据读入缓冲区,并执行回调函数,处理这条消息。我们并不需要关心这条消息何时到达。
     
    二、什么情况下我们用异步Socket:
     
    有些人认为,异步Socket的性能比同步Socket的性能高很多,应该在各种环境下都用异步Socket,其实不然。在某些环境下面。异步反到比同步的性能低,那么在哪些情况下会这样呢?
     
    1、客户端Socket。
     
    2、服务端连接数比较少。
     
    3、连接数很多,但都是短连接。
     
    在这些环境下,我们用同步Socket不但可以简化代码,而且性能并不会比异步Socket低。但在服务端连接比较多而且是长连接的情况下,我们就要使用异步Socket。
     
    现在我们来看看如何用异步Socket编程。
     
    首先,我们要建立一个Socket用来监听:

    Socket _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    IPEndPoint localEP
    = new IPEndPoint(_address, _port);
    _listener.Bind(localEP);
    _listener.Listen(
    100);
    然后创建一个线程来处理客户端连接请求:
    Thread _acceptWorkThread = new Thread(AcceptWorkThread);
    _acceptWorkThread.Start();

    private void AcceptWorkThread()
    {
    while (_isListener)
    {
    UserInfo info
    = new UserInfo();//这个UserInfo是用来保存客户信息的。
    info.socket = socket;
    Socket socket
    = _listener.Accept();
    //这里进行其它处理。
    socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, ReceiveCallBack, info);//这里向系统投递一个接收信息的请求,并为其指定ReceiveCallBack做为回调函数
    }
    }
    我们再来看看回调函数的定义:
    private void ReceiveCallBack(IAsyncResult ar)
    {
    UserInfo info
    = (UserInfo)ar.AsyncState;
    Socket handler
    = info.socket;
    int readCount = 0;
    try
    {
    readCount
    = handler.EndReceive(ar);//调用这个函数来结束本次接收并返回接收到的数据长度。
    }
    catch (SocketException)//出现Socket异常就关闭连接
    {
    CloseSocket(info);
    //这个函数用来关闭客户端连接
    return;
    }
    catch
    {
    }
    if (readCount > 0)
    {
    byte[] buffer = new byte[readCount];
    Buffer.BlockCopy(info.Buffer,
    0, buffer, 0, readCount);
    Analyzer(info, buffer);
    //这个函数用来处理接收到的信息。
    try
    {
    handler.BeginReceive(info.Buffer,
    0, info.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), info);//向系统投递下一个接收请求
    }
    catch (SocketException) //出现Socket异常就关闭连接
    {
    CloseSocket(info);
    }
    catch
    {
    }
    }
    else //如果接收到0字节的数据说明客户端关闭了Socket,那我们也要关闭Socket
    {
    CloseSocket(info);
    }
    }
     
    接下来我们看看如何发送数据给客户端:
    public void Send(Socket socket, byte message)
    {
    try
    {
    info.socket.BeginSend(message,
    0, _byte.Length, SocketFlags.None, new AsyncCallback(SendCallBack), info);//这里向系统投递一个发送数据的请求,并指定一个回调函数。
    }
    catch (SocketException ex)
    {
    CloseSocket(info);
    }
    catch
    {
    }
    }
    定义发送回调函数:
    private void SendCallBack(IAsyncResult ar)
    {
    UserInfo info
    = (UserInfo)ar.AsyncState;
    try
    {
    info.socket.EndSend(ar);
    //调用这个函数来结束本次发送。
    }
    catch
    {
    }
    }
    好了,整个监听、接收、发送的过程就完成了,很简单吧。现在需要说明的是,我在这里接收客户端连接的Accept是用的同步的,我个人认为在这里用同步的会比用异步好一些。因为这样代码简单而且没有性能上的损失。
    今天我就写到这里了!下次我们再继续。
  • 相关阅读:
    Centos7 Crontab
    Centos7 php-fpm root 运行,执行 kill 等系统命令
    Centos7 安装系统服务、开机自启动
    CentOS7 安装Python3,开发SocketIO 客户端
    Centos7.6 安装DNS服务器
    exerunexplorer.exe
    Web GIS 离线地图
    DataGridView中添加CheckBox列用于选择行
    Android WebView Demo
    上海华魏光纤传感科技有限公司 招聘 《.NET研发工程师》
  • 原文地址:https://www.cnblogs.com/ChangTan/p/2050399.html
Copyright © 2011-2022 走看看