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

    转自:http://www.cnblogs.com/wzd24/archive/2007/06/13/782833.html

    在基于.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是用的同步的,我个人认为在这里用同步的会比用异步好一些。因为这样代码简单而且没有性能上的损失。

    今天我就写到这里了!下次我们再继续。

  • 相关阅读:
    201521044091《Java程序设计》第7周学习总结
    201521044091《java程序设计》第四次总结
    201521044091 《java程序设计》第八周学习总结
    201521044091 《Java程序设计》第5周学习总结
    201521044091 《Java程序设计》第2周学习总结
    201521044091 《Java程序设计》第3周学习总结
    MySQL设置字符集CHARACTER SET
    Create My MySQL configuration by Percona
    How to use jQuery to manipulate Cookies
    How to use OpenXml to import xml data to Sql server
  • 原文地址:https://www.cnblogs.com/dooom/p/1831179.html
Copyright © 2011-2022 走看看