• Socket调用方式(同步,异步,阻塞,非阻塞)


    同步:

    我调用一个功能,该功能没有结束前,我死等结果。

    异步:

    当一个异步过程调用发出后,调用者不能立刻得到结果。该功能在完成后,通过状态、通知和回调来通知调用者。

    同步和非同步关注的是调用者是否等待等待调用结果。

    举个通俗的例子:
    你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
    而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

    阻塞

    调用我(函数),我(函数)没有接收完数据或者没有得到结果之前,我不会返回。

    非阻塞

    调用我(函数),我(函数)立即返回通知调用者

    以最常用的send和recv两个函数为例
    比如你调用send函数发送一定的Byte,在系统内部send做的工作其实只是把数据传输(Copy)到TCP/IP协议栈的输出缓冲区,它执行成功并不代表数据已经成功的发送出去了,如果TCP/IP协议栈没有足够的可用缓冲区来保存你Copy过来的数据的话...这时候就体现出阻塞和非阻塞的不同之处了:对于阻塞模式的socket send函数将不返回直到系统缓冲区有足够的空间把你要发送的数据Copy过去以后才返回,而对于非阻塞的socket来说send会立即返回WSAEWOULDDBLOCK告诉调用者说:"发送操作被阻塞了!!!你想办法处理吧..." 
    对于recv函数,同样道理,对于阻塞模式的socket来说如果TCP/IP协议栈的接收缓冲区没有通知一个结果给它它就一直不返回:耗费着系统资源....对于非阻塞模式的socket该函数会马上返回,然后告诉你:WSAEWOULDDBLOCK---"现在没有数据,回头再来看看"

    阻塞I/O模型:

    非阻塞I/O模型:

    阻塞和非阻塞关注的是调用者在等待调用结果时的状态。

    还是上面的例子,
    你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。

    同步异步与阻塞非阻塞的关系:

    • 在处理 IO 的时候,阻塞和非阻塞都是同步 IO。socket接收数据的recv函数,如果没有数据的情况下调用该函数,则当前线程就会被挂起,直到有数据为止(同步&阻塞);CSocket中调用Receive函数,如果缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回,而此时,当前线程还会继续处理各种各样的消息(同步&非阻塞)。
    • 只有使用了特殊的 API 才是异步 IO。

    异步调用的方式:

    Javascript语言的执行环境是"单线程"(single thread)。所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队。解决方法:实现异步。
    例1:回调函数。A先告诉B去点亮,然后自己点亮。B的点亮操作并不会阻塞A。
    复制代码
    function lightUp(A, callback){ 
    
     callback(); 
    
     A.lightUp(); 
    
    } 
    
    function callback(){
    
     B.lightUp(); 
    
    }
    复制代码
    ***同步调用时这样的***
    复制代码
    var temp = false; 
    
    while(!temp){
      temp = wait(A.lightUp());
    }
    
    B.lightUp();
    复制代码
    例2:事件监听。
    复制代码
    function AlightUp(){ 
    
     this.trigger('done'); 
    
     this.do(); 
    
    } 
    
    function BlightUp(){ 
    
     this.do(); 
    
    }
    AlightUp.on('done',BlightUp);
    复制代码
    例3:发布/订阅。
    复制代码
    jQuery.subscribe("done", f2); 
    function f1(){
      setTimeout(function () {
        // f1的任务代码
        jQuery.publish("done");
      }, 1000);
    }  
    复制代码
    f2完成执行后,也可以取消订阅(unsubscribe)。
    jQuery.unsubscribe("done", f2); 
    这种方法的性质与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。
     
    例4:Promises
    Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。
    简单说,它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:
    复制代码
    f1().then(f2); 
    function f1(){
      var dfd = $.Deferred();
      setTimeout(function () {
        // f1的任务代码
        dfd.resolve();
      }, 500);
      return dfd.promise;
    } 
    复制代码
    这样写的优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚。
    比如,指定多个回调函数:f1().then(f2).then(f3); 
    再比如,指定发生错误时的回调函数:f1().then(f2).fail(f3);
  • 相关阅读:
    Qt计算器开发(三):执行效果及项目总结
    [HNOI2019]校园旅行
    How to fix nuget Unrecognized license type MIT when pack
    How to fix nuget Unrecognized license type MIT when pack
    git 通过 SublimeMerge 处理冲突
    git 通过 SublimeMerge 处理冲突
    git 上传当前分支
    git 上传当前分支
    gif 格式
    gif 格式
  • 原文地址:https://www.cnblogs.com/qionglouyuyu/p/4823611.html
Copyright © 2020-2023  润新知