套接字应用程序

news2024/10/7 8:13:23
这章节是关于实现 lib_chan 库的 lib_chan 的代码在 TCP/IP 之上实现了一个完整的网络层,能够提供认证和Erlang 数据流功能。一旦理解了 lib_chan 的原理,就能量身定制我们自己的通信基础结构,并把它叠加在TCP/IP 之上了。 就lib_chan 本身而言,它是一种构建分布式系统的有用组件。

一:简单示例:

用一个简单的示例来展示如何使用 lib_chan 。我们会创建一个简单的服务器,让它 计算阶乘和斐波那契数,并用一个密码来保护它。 这个服务器将在2233 端口工作。
创建服务器的过程共分四步。
(1) 编写配置文件。
(2) 编写服务器代码。
(3) 启动服务器。
(4) 通过网络访问服务器。

1. 编写配置文件

下述代码时这个示例的配置文件:

%% socket_dist/config1
{port,2233}.
{service, math, password, "qwerty", mfa, mod_math, run, []}.
这个配置文件里有一些 service 元组,它们的形式如下:
{service, <Name>, password, <P>, mfa, <Mod>, <Func>, <ArgList>}
里面的参数由原子 servicepassword mfa 分隔。 mfa module, function, args ”的缩写, 意思是接下来的三个参数应当被解释为模块名、函数名和一个用来调用函数的参数列表。 在我们的示例里,配置文件指定了一个名为math (数学)的服务,它的工作端口是 2233 。这个服务由密码qwerty 保护,实现它的模块名为 mod_math ,启动方式是调用 mod_math:run/3 , run/3的第三个参数是 [ ]

2.编写服务器代码

这个数学服务器的代码如下:
%% socket_dist/mod_math.erl
-module(mod_math).
-export([run/3]).

run(MM, ArgC, Args) ->
    io:format("mod_math:run_starting~n"
              "Argc = ~p Args = ~p~n",[ArgC, Args]),
    loop(MM).

loop(MM) ->
    receive
        {chan, MM, {factorial, N}} ->
            MM !{send, fac(N)},
            loop(MM);
        {chan, MM, {fibonacci, N}} ->
            MM !{send, fib(N)},
            loop(MM);
        {chan_closed, MM} ->
            io:format("mod_math stopping~n"),
            exit(normal)
    end.

fac(0) -> 1;
fac(N) -> N*fac(N-1).
fib(1) -> 1;
fib(2) -> 1;
fib(N) -> fib(N-1) + fib(N-2).
当某个客户端连接到 2233 端口并请求 math 服务时, lib_auth 会对它进行认证,如果密码正确,就会通过mod_math:run(MM, ArgC, ArgS) 函数分裂出一个处理进程。 MM 中间人 PID , ArgC来自客户端, ArgS 则来自配置文件。这个数学服务器很简单,它所做的就是等待一个 {chan, MM, {factorial, N}}消息,然后执行 MM ! {send, fac(N)}来把结果发回客户端。

3.启动服务器

像下面这样启动服务器:
1> lib_chan:start_server("./configl").
ConfigData = [{port,2233},{service,math,password,"qwerty",mfa,mod_math,run,[]}
true

4.通过网络访问服务器

可以在单台机器上进行代码测试:
2> {ok, S} = lib_chan:connect("localhost", 2233, math,
                              "qwerty", {yes, go}).
{ok,<0.47.0>}

3> lib_chan:rpc(S, {factorial, 20}).
2432902008176640000

4> lib_chan:rpc(S, {fibonacci, 15}).
610

5> lib_chan:disconnect(S).
close

二:lib_chan的原理

构建 lib_chan 使用了四个模块里的代码。
(1)  lib_chan 扮演“主模块”的角色。程序员只需要了解 lib_chan 所导出的那些方法。其他
三个模块(稍后讨论)会在 lib_chan 的内部使用。
(2)  lib_chan_mm 负责编码和解码 Erlang 消息,并管理套接字通信。
(3)lib_chan_cs 负责设立服务器并管理客户端连接。它的主要工作之一是限制同时连接的
最大客户端数量。
(4)  lib_chan_auth 包含的代码用于进行简单的质询 / 响应认证。

1. lib_chan

lib_chan 的结构如下:
-module(lib_chan).
start_server(ConfigFile) ->
    %% 读取配置文件并检查语法
    %% 调用start_port_server(Port, ConfigData)
    %% 其中Port是所需的端口,ConfigData包含配置数据
    ...

start_port_server(Port, ConfigData) ->
     lib_chan_cs:start_raw_server(
          fun(Socket) ->
               start_port_instance(Socket, ConfigData),
          end, ...).
     %% Lib_chan_cs负责管理连接。
     %% 新连接建立后会胡用start_raw_server的参数,
     %% 也就是这个fUn。
start_port_instance(Socket, ConfigData) ->
    %% 它会在客户瑞连接服务器时执行分裂。
    %% 我们会设立一个中间人并执行认证,
    %% 如果一切顺利就调用
    %% really_start (MM, ArgC, {Mod,Func,ArgS})
    %% (后三个参数来自配置文件)
    ....

really_start(MM, ArgC, {Mod, Func, Args}) ->
   apply(Mod, Func, [MM, ArgC, Args]).

connect(Host,Port,Service,Password,Argc)->
    %% 客户瑞代码
    ...

2.lib_chan_mm中间人

lib_chan_mm 实现了一个中间人。它能对应用程序隐藏套接字通信,并把 TCP 套接字上的数据流转变成Erlang 消息。中间人负责组装消息(它可能是碎片化的)和编码 / 解码 Erlang 数据类型,也就是把它们转换成能通过套接字发送和接收的字节流。可以通过下图来进行理解:

带中间人的套接字通信
M1 机器上的 MM1 进程表现得就像是 P2 的代理,而在 M2 机器上的 MM2 进程表现得就像是 P1
代理。 MM1和 MM2 都是中间人进程的 PID 。中间人进程的代码如下:
loop(Socket, Pid) ->
    receive
        {tcp, Socket, Bin} ->
            Pid ! {chan, self(), binary_to_term(Bin)},
            loop(Socket, Pid);
        {tcp_closed, Socket} ->
            Pid ! {chan_closed, self()};
        close ->
            gen_tcp:close(Socket);
        {send, T} ->
            gen_tcp:send(Socket, [term_to_binary(T)]),
            loop(Socket, Pid)
    end.
这个循环是套接字数据和 Erlang 消息传输这两个世界之间的接口。

3.lib_chan_cs

lib_chan_cs 负责设立客户端和服务器通信。下面是它导出的两个重要方法:
(1) start_raw_server(Port, Max, Fun, PacketLength)
        它会启动一个监听器来监听Port上的连接。允许的最大同时会话数是Max。Fu是一个元数为1的fin,Fun(Socket)会在连接开始时执行。套接字通信会假定包长度为PacketLength。
(2) start:raw_client(Host, Port, PacketLength) => {ok, Socket} | {error, Why}
        它会尝试连接由start_raw_server打开的端口。

4. lib_chan_auth

如果某个客户端想使用 math 服务,就必须向服务器证明它知道共享秘密。这个过程如下所示:
(1) 客户端向服务器发送一个请求来表示它希望使用 math 服务。
(2) 服务器计算出一个随机字符串 C ,然后把它发给客户端。这就是 质询 。字符串是由 lib_chan_auth:make_challenge()函数生成的。可以用交互方式来看它是如何工作的:
1> C = lib_chan_auth:make_challenge().
"qnyrgzqefvnjdombanrsmxikc"
(3) 客户端接收字符串( C )并计算出响应( R ),其中 R = MD5(C  ++ Secret) ,它是由
lib_chan_auth:make_response 生成的。这里有一个例子:
2> R = lib_chan_auth:make_response(C,"qwerty").
"e759ef3778228beae988d91a67253873"

(4)这个响应被发回服务器。服务器接收响应并检查它是否正确,做法是算出预期的响应值。 这是由lib_chan_auth:is_response_correct实现的。如下:

3> lib_chan_auth:is_response_correct(C, R, "qwerty").
true 

完整的lib_chan代码我打算单独列一篇来记录,因此本章就介绍一个例子和原理。

想要看lib_chan的详细代码可以跳转到下一篇:

http://t.csdnimg.cn/MXOOy

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1296817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PSP - 计算蛋白质复合物链间接触的残基与面积

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/134884889 在蛋白质复合物中&#xff0c;通过链间距离&#xff0c;可以计算出在接触面的残基与接触面的面积&#xff0c;使用 BioPython 库 与 SA…

在Pytorch中使用Tensorboard可视化训练过程

这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 本节课我们来讲一下如何在pytouch当中去使用我们的tensorboard 对我们的训练过程进行一个可视化 左边有一个visualizing models data and training with tensorboard 主要是这么一个教程 那么这里…

28BYJ-48步进电机的驱动

ULN2003的工作原理 28BYJ48可以用ULN2003来驱动&#xff0c;STM32使用开漏模式外接5V上拉电阻也可以产生5V电压&#xff0c;为什么不直接使用单片机的 GPIO来驱动的原因是虽然电压符合电机的驱动要求&#xff0c;但单片机引脚产生的驱动电流太小&#xff0c;因此驱动步进电机要…

IBM Qiskit量子机器学习速成(四)

量子核机器学习 一般步骤 量子核机器学习的一般步骤如下 定义量子核 我们使用FidelityQuantumKernel类创建量子核&#xff0c;该类需要传入两个参数&#xff1a;特征映射和忠诚度(fidelity)。如果我们不传入忠诚度&#xff0c;该类会自动创建一个忠诚度。 注意各个类所属的…

leaflet:经纬度坐标转为地址,点击鼠标显示地址信息(137)

第137个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中将经纬度坐标转化为地址,点击鼠标显示某地的地址信息 。主要利用mapbox的api将坐标转化为地址,然后在固定的位置显示出来。 直接复制下面的 vue+leaflet源代码,操作2分钟即可运行实现效果 文章目录 示…

UniDBGrid序号列添加标题

有人想要在UniDBGrid的序号列加上标题&#xff0c;就是这里 可以使用如下代码 UniSession.AddJS(MainForm.UniDBGrid1.columnManager.columns[0].setText("序号"));

VMware安装Ubuntu20.04并使用Xshell连接虚拟机

文章目录 虚拟机环境准备重置虚拟网络适配器属性&#xff08;可选&#xff09;配置NAT模式的静态IP创建虚拟机虚拟机安装配置 Xshell连接虚拟机 虚拟机环境准备 VMware WorkStation Pro 17.5&#xff1a;https://customerconnect.vmware.com/cn/downloads/details?downloadGr…

样本数量对问卷信度效度分析的影响及应对策略

问卷调研是一种常见的数据收集方法。明确问卷的真实性和效率是保证其靠谱性和有效性的重要一步。但问卷的真实性和品质会受到样本数量的影响吗&#xff1f; 一、问卷信度的认识 1、信度的概念和重要性:在问卷实验中&#xff0c;信度是指问卷测量值的稳定性和一致性。高信度代…

go grpc高级用法

文章目录 错误处理常规用法进阶用法原理 多路复用元数据负载均衡压缩数据 错误处理 gRPC 一般不在 message 中定义错误。毕竟每个 gRPC 服务本身就带一个 error 的返回值&#xff0c;这是用来传输错误的专用通道。gRPC 中所有的错误返回都应该是 nil 或者 由 status.Status 产…

希尔排序详解:一种高效的排序方法

在探索排序算法的世界中&#xff0c;我们经常遇到需要对大量数据进行排序的情况。传统的插入排序虽然简单&#xff0c;但在处理大规模数据时效率并不高。这时&#xff0c;希尔排序&#xff08;Shell Sort&#xff09;就显得尤为重要。本文将通过深入解析希尔排序的逻辑&#xf…

分享十几个适合新手练习的软件测试项目

说实话&#xff0c;在找项目的过程中&#xff0c;我下载过&#xff08;甚至付费下载过&#xff09;N多个项目、联系过很多项目的作者&#xff0c;但是绝大部分项目&#xff0c;在我看来&#xff0c;并不适合你拿来练习&#xff0c;它们或多或少都存在着“问题”&#xff0c;比如…

编写一个程序, 给出两个时间,计算出两个时间之差,如给出1120表示11:20,1330表示13:30, 将时间间隔以分钟为单位输出。

如下: #include<stdio.h>int main(){int a,b;printf("请输入第一个时间a:");scanf("%d",&a);printf("请输入第二个时间b:");scanf("%d",&b);int hour1a/100;//取小时int minute1a%100;//取分钟int hour2b/100;int minu…

HCIP --- BGP 基础 (中)

BGP的数据包 Open、Update、Notification、Keepalive、Route-refresh BGP的公共头部 Marker &#xff1a;标记 &#xff08;可以兼容字段、版本&#xff09; 全F Length&#xff1a; 标明数据包多长多大 Type&#xff1a;表明数据包类型&#xff08;可选 12345&#xff09; …

如何切换用户和更改用户密码

https://blog.csdn.net/u012759006/article/details/89681615 https://blog.csdn.net/Z_CAIGOU/article/details/120925716 1、sudo su 切换到root用户 2、passwd 用户名 之后输入你修改后的密码两次&#xff0c;成功。 文章知识点与官方知识档案匹配&#xff0c;可 一般情…

C语言 扫雷游戏

代码在一个项目里完成&#xff0c;分成三个.c.h文件(game.c,game.h,main.c) 在Clion软件中通过运行调试。 /大概想法/ 主函数main.c里是大框架(菜单,扫雷棋盘初始化&#xff0c;随机函数生成雷&#xff0c;玩家扫雷) game.h函数声明(除main函数和游戏函数外的一些函数声明) ga…

Kafka安全性探究:构建可信赖的分布式消息系统

在本文中&#xff0c;将研究Kafka的安全性&#xff0c;探讨如何确保数据在传输和存储过程中的完整性、机密性以及授权访问。通过详实的示例代码&#xff0c;全面讨论Kafka安全性的各个方面&#xff0c;从加密通信到访问控制&#xff0c;帮助大家构建一个可信赖的分布式消息系统…

品牌控价成本如何把控

品牌在发展&#xff0c;价格就需要持续关注&#xff0c;当出现乱价、低价、窜货时就应投入人力去治理&#xff0c;但企业生存&#xff0c;还要考虑成本&#xff0c;如何在保证控价效果的基础上&#xff0c;做到使用最低成本呢&#xff0c;这些问题除了控价本身外&#xff0c;也…

苹果IOS在Safari浏览器中将网页添加到主屏幕做伪Web App,自定义图标,启动动画,自定义名称,全屏应用pwa

在ios中我们可以使用Safari浏览自带的将网页添加到主屏幕上&#xff0c;让我们的web页面看起来像一个本地应用程序一样&#xff0c;通过桌面APP图标一打开&#xff0c;直接全屏展示&#xff0c;就像在APP中效果一样&#xff0c;完全体会不到你是在浏览器中。 1.网站添加样式 在…

去掉手机端顶部间隙

Unigui手机端打开时&#xff0c;在顶部有一条白色间隙 使用以下方法可以去除间隙 在ServerModule的customcss里添加以下代码 body{ margin:0!important; padding:0!important; }

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《考虑垃圾处理与调峰需求的可持续化城市多能源系统规划》

这个标题涵盖了城市多能源系统规划中的两个重要方面&#xff1a;垃圾处理和调峰需求&#xff0c;并强调了规划的可持续性。 考虑垃圾处理&#xff1a; 含义&#xff1a; 垃圾处理指的是城市废弃物的管理和处置。这可能涉及到废物分类、回收利用、焚烧或填埋等方法。重要性&…