热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

gen_tcp的被动模式和一次模式之间的区别

如何解决《gen_tcp的被动模式和一次模式之间的区别》经验,为你挑选了1个好方法。

我正在阅读编程Erlang 2E.在第17章的主动和被动套接字中,它说:

您可能认为对所有服务器使用被动模式是正确的方法.不幸的是,当我们处于被动模式时,我们只能等待来自一个套接字的数据.这对于编写必须等待来自多个套接字的数据的服务器毫无用处.

幸运的是,我们可以采用混合方法,既不阻塞也不阻塞.我们使用选项{active,once}打开套接字.在此模式下,套接字处于活动状态,但仅适用于一条消息.在控制进程发送消息后,它必须显式调用inet:setopts以重新启用下一条消息的接收.系统将阻止,直到发生这种情况.这是两全其美的.

相关代码:

% passive mode
loop(Socket) ->     
    ?case? gen_tcp:recv(Socket, N) ?of??    
        {ok, B} ->?     
            ... do something with the data ...?     
            loop(Socket);?  
        {error, closed}?    
            ...?    
    ?end?.

% once mode
loop(Socket) ->     
    ?receive??  
        {tcp, Socket, Data} ->?     
            ... do something with the data ...?     
            ?%% when you're ready enable the next message??     
            inet:setopts(Sock, [{active, once}]),?  
            loop(Socket);?  
        {tcp_closed, Socket} ->?    
            ...?    
    ?end?.

我没有看到两者之间有任何真正的区别.gen_tcp:recvpassive模式本质上是做同样的事情receiveonce模式.once模式如何解决此passive模式问题:

不幸的是,当我们处于被动模式时,我们只能等待来自一个套接字的数据.这对于编写必须等待来自多个套接字的数据的服务器毫无用处.

zxq9.. 7

主要区别在于您选择对该套接字上的事件做出反应.使用活动套接字,您的进程会收到一条消息,带有被动套接字,您必须自己决定调用gen_tcp:recv.这对你意味着什么?

编写Erlang程序的典型方法是让它们对事件做出反应.在该主题之后,大多数Erlang进程等待表示外部事件的消息,并根据其性质对它们做出反应.当您使用活动套接字时,您可以以与其他事件完全相同的方式对套接字数据进行编程:作为Erlang消息.当您使用被动套接字编写时,您必须选择何时检查套接字以查看它是否有数据,并对何时检查Erlang消息做出不同的选择 - 换句话说,您最终必须编写轮询例程,并且这错过了Erlang的许多优点.

所以active_onceactive... 之间的区别

使用活动套接字,任何能够建立连接的外部参与者都可以使用数据包轰炸进程,无论系统是否能够跟上.如果您想象一个具有一千个并发连接的服务器,其中每个数据包的接收需要一些重要的计算或访问某些其他有限的外部资源(不是这种奇怪的情况),您最终必须选择如何处理过载.

只有active套接字你已经做出了选择:你会让服务降级,直到事情开始失败(超时或其他).

有了active_once插座,你有机会做出一些选择.一个active_once插座,您会收到一个插座上的信息,并将它passive再次,直到你把它重置active_once.这意味着您可以编写一个阻塞/同步调用来检查整个系统是否安全地继续处理消息并在处理结束和receive侦听套接字的下一个开始之间插入消息- 甚至选择receive在系统过载的情况下进入而不重新激活套接字,但您的进程需要在此期间处理其他Erlang消息.

想象一下,一个名为的进程被调用sysmon,它存在于该节点上,并检查外部数据库是否正在过载.您的进程可以接收数据包,对其进行处理,并让系统监视器知道它已准备好进行更多工作,然后再允许套接字向其发送另一条消息.系统监视器还可以向侦听进程发送消息,告诉他们在侦听数据包暂时停止接收数据,这是gen_tcp:recv方法无法实现的(因为您要么接收套接字数据,要么检查Erlang消息,但不能同时检查两者):

loop(S = {Socket, OtherState}) ->
    sysmon ! {self(), ready},
    receive
        {tcp, Socket, Data} ->
            ok = process_data(Data, OtherState),
            loop(S);
        {tcp_closed, Socket} ->
            retire(OtherState),
            ok;
        {sysmon, activate} ->
            inet:setopts(Socket, [{active, once}]),
            loop(S);
        {sysmon, deactivate} ->
            inet:setopts(Socket, [{active, false}]),
            loop(S);
        {other, message} ->
            system_stuff(OtherState),
            loop(S)
    end.

这是实现系统范围限制的一种方式的开始,使得处理通常最困难的部分变得容易:跨网络,系统外部以及完全不受控制的元素.如果再加上一些早期的决策(比如"在完全拒绝新连接之前我们需要多少负载?"),这种能够接收套接字数据作为Erlang消息,但不会让自己受到被它们轰炸(或填满你的邮箱,使得寻找非套接字消息任意昂贵),与手动处理套接字相比,我们在石器时代(甚至今天在其他语言中)的方式感觉相当神奇.

这是LYSE的作者Fred Hebert关于过载的一篇有趣的文章:"队列不要修复过载".它并不是特定于Erlang,但他所写的想法在Erlang中比大多数其他语言更容易实现,这可能与将队列(误导)用作容量管理技术的普遍性有关.



1> zxq9..:

主要区别在于您选择对该套接字上的事件做出反应.使用活动套接字,您的进程会收到一条消息,带有被动套接字,您必须自己决定调用gen_tcp:recv.这对你意味着什么?

编写Erlang程序的典型方法是让它们对事件做出反应.在该主题之后,大多数Erlang进程等待表示外部事件的消息,并根据其性质对它们做出反应.当您使用活动套接字时,您可以以与其他事件完全相同的方式对套接字数据进行编程:作为Erlang消息.当您使用被动套接字编写时,您必须选择何时检查套接字以查看它是否有数据,并对何时检查Erlang消息做出不同的选择 - 换句话说,您最终必须编写轮询例程,并且这错过了Erlang的许多优点.

所以active_onceactive... 之间的区别

使用活动套接字,任何能够建立连接的外部参与者都可以使用数据包轰炸进程,无论系统是否能够跟上.如果您想象一个具有一千个并发连接的服务器,其中每个数据包的接收需要一些重要的计算或访问某些其他有限的外部资源(不是这种奇怪的情况),您最终必须选择如何处理过载.

只有active套接字你已经做出了选择:你会让服务降级,直到事情开始失败(超时或其他).

有了active_once插座,你有机会做出一些选择.一个active_once插座,您会收到一个插座上的信息,并将它passive再次,直到你把它重置active_once.这意味着您可以编写一个阻塞/同步调用来检查整个系统是否安全地继续处理消息并在处理结束和receive侦听套接字的下一个开始之间插入消息- 甚至选择receive在系统过载的情况下进入而不重新激活套接字,但您的进程需要在此期间处理其他Erlang消息.

想象一下,一个名为的进程被调用sysmon,它存在于该节点上,并检查外部数据库是否正在过载.您的进程可以接收数据包,对其进行处理,并让系统监视器知道它已准备好进行更多工作,然后再允许套接字向其发送另一条消息.系统监视器还可以向侦听进程发送消息,告诉他们在侦听数据包暂时停止接收数据,这是gen_tcp:recv方法无法实现的(因为您要么接收套接字数据,要么检查Erlang消息,但不能同时检查两者):

loop(S = {Socket, OtherState}) ->
    sysmon ! {self(), ready},
    receive
        {tcp, Socket, Data} ->
            ok = process_data(Data, OtherState),
            loop(S);
        {tcp_closed, Socket} ->
            retire(OtherState),
            ok;
        {sysmon, activate} ->
            inet:setopts(Socket, [{active, once}]),
            loop(S);
        {sysmon, deactivate} ->
            inet:setopts(Socket, [{active, false}]),
            loop(S);
        {other, message} ->
            system_stuff(OtherState),
            loop(S)
    end.

这是实现系统范围限制的一种方式的开始,使得处理通常最困难的部分变得容易:跨网络,系统外部以及完全不受控制的元素.如果再加上一些早期的决策(比如"在完全拒绝新连接之前我们需要多少负载?"),这种能够接收套接字数据作为Erlang消息,但不会让自己受到被它们轰炸(或填满你的邮箱,使得寻找非套接字消息任意昂贵),与手动处理套接字相比,我们在石器时代(甚至今天在其他语言中)的方式感觉相当神奇.

这是LYSE的作者Fred Hebert关于过载的一篇有趣的文章:"队列不要修复过载".它并不是特定于Erlang,但他所写的想法在Erlang中比大多数其他语言更容易实现,这可能与将队列(误导)用作容量管理技术的普遍性有关.


推荐阅读
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 本文介绍了Redis中RDB文件和AOF文件的保存和还原机制。RDB文件用于保存和还原Redis服务器所有数据库中的键值对数据,SAVE命令和BGSAVE命令分别用于阻塞服务器和由子进程执行保存操作。同时执行SAVE命令和BGSAVE命令,以及同时执行两个BGSAVE命令都会产生竞争条件。服务器会保存所有用save选项设置的保存条件,当满足任意一个保存条件时,服务器会自动执行BGSAVE命令。此外,还介绍了RDB文件和AOF文件在操作方面的冲突以及同时执行大量磁盘写入操作的不良影响。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 从Oracle安全移植到国产达梦数据库的DBA实践与攻略
    随着我国对信息安全和自主可控技术的重视,国产数据库在党政机关、军队和大型央企等行业中得到了快速应用。本文介绍了如何降低从Oracle到国产达梦数据库的技术门槛,保障用户现有业务系统投资。具体包括分析待移植系统、确定移植对象、数据迁移、PL/SQL移植、校验移植结果以及应用系统的测试和优化等步骤。同时提供了移植攻略,包括待移植系统分析和准备移植环境的方法。通过本文的实践与攻略,DBA可以更好地完成Oracle安全移植到国产达梦数据库的工作。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
author-avatar
胖妞-Debbie_982
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有