• 浅谈C#网络编程(二)


    阅读目录:

    1. 异步IO
    2. 非阻塞式同步IO
    3. 基于回调的异步IO并发

    异步IO

    上篇提到用多线程处理多个阻塞同步IO而实现并发服务端,这种模式在连接数量比较小的时候非常适合,一旦连接过多,性能会急速下降。 在大多数服务端网络软件中会采用一种异步IO的方式来提高性能。

    • 同步IO方式:连接Receive请求->等待->等待->接收成功
    • 异步IO方式:连接Receive请求->立即返回->事件或回调通知

    采用异步IO方式,意味着单线程可以处理多个请求了,连接发起一个Receive请求后,当前线程可以立即去做别的事情,当数据接收完毕通知线程处理即可。
    其数据接收分2部分:

    1. 数据从别的机器发送内核缓冲区
    2. 内核缓冲区拷贝到用户缓冲区

    第二部分示例代码:

    byte[] msg = new byte[256]; socket.Receive(msg);

    介绍这2部分的目的是方便区分其他几种方式。 对于用户程序来说,同步IO和异步IO的区别在于第二部分是否需要等待。

    非阻塞式同步IO

    非阻塞式同步IO,由同步IO延伸出来,把这个名词拆分成2部分描述:

    1. 非阻塞式,指的是上节"数据从别的机器发送内核缓冲区"部分是非阻塞的。
    2. 同步IO,指的是上节"内核缓冲区拷贝到用户缓冲区"部分是等待的。

    既然是第一部分是非阻塞的,那就需要一种方法得知什么时候内核缓冲区是OK的。 设置非阻塞模式后,在连接调用Receive方法时,会立即返回一个标记,告知用户程序内核缓存区有没有数据,如果有数据开始进行第二部分操作,从内核缓冲区拷贝到用户程序缓冲区。 由于系统会返回个标记,那可以通过轮询方式来判断内核缓冲区是否OK。

    设置非阻塞模式参考代码:

    SocketInformation sif=new SocketInformation();
    sif.Options=SocketInformationOptions.NonBlocking;
    sif.ProtocolInformation = new byte[24];
    Socket socket = new Socket(sif);

    轮询参考代码:

    while(true) 
    {
    byte[] msg = new byte[256];
    var temp = socket.Receive(msg);
    if (temp=="OK"){
    //do something
    }else{ continue }
    }

     这种方式近乎淘汰了,了解即可。

    基于回调的异步IO

    上面介绍过:

    • 异步IO方式:连接Receive请求->立即返回->事件或回调通知

    当回调到执行时,数据已经在用户程序缓冲区已经准备好了,在回调代码中对这部分数据进行相应的逻辑即可。

    发出接收请求:

     static byte[] msg = new byte[256]; var temp = socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(ReadCallback), socket);

    回调函数中对数据做处理:

    public static void ReadCallback(IAsyncResult ar) 
    { 
    var socket = (Socket)ar.AsyncState;
     int read = socket.EndReceive(ar);
    DoSomething(msg); 
    socket.BeginReceive(msg, 0, msg.Length, 0, new AsyncCallback(Read_Callback), socket);
    }

     当回调函数执行时,表示数据已经准备好,需要先结束接收请求EndReceive,以便第二次发出接收请求。 在服务端程序中要处理多个客户端的接收,再次发出BeginReceive接收数据请求即可。

    这里的回调函数是在另外一个线程的触发,必要时要对数据加锁防止数据竞争:

    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
  • 相关阅读:
    钾 动态规划
    镁 细节
    锌 填坑计划
    钠 GZY整理贪心
    javascript+Java 实现MD5加密登录密码
    FCKeditor2.6.4图片上传,中文名乱码,红叉各种问题解决
    Java 随机生成验证码,支持大小写字母、数字、随机字体
    BI BI系统监控
    使用ETL控件还是存储过程
    fsync与数据库日志刷新
  • 原文地址:https://www.cnblogs.com/mushroom/p/4850083.html
Copyright © 2020-2023  润新知