套接字应用程序

这章节是关于实现 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}).
24329020081766400004> lib_chan:rpc(S, {fibonacci, 15}).
6105> 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.mzph.cn/news/207410.shtml

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

相关文章

MMLM之Gemini:《Introducing Gemini: our largest and most capable AI model》的翻译与解读

MMLM之Gemini&#xff1a;《Introducing Gemini: our largest and most capable AI model》的翻译与解读 导读&#xff1a;2023年12月6日&#xff0c;Google重磅发布大规模多模态模型Gemini&#xff0c;表示了Google语言模型发展到了一个新阶段&#xff0c;其多模态和通用能力明…

中断、异常和系统调用(2-1,2-2,2-3)

2-1 课堂练习2.1&#xff1a;外部中断 本实训分析 Linux 0.11 对外部中断的响应和处理过程。在每条指令执行的末尾&#xff0c;如果没有关中断&#xff0c;CPU 会检查是否收到了外部中断信号&#xff0c;如果有信号&#xff0c;则 CPU 就切换到核心态去执行对应的中断处理程序…

DHTMLX Scheduler PRO 6.0.5 Crack

功能丰富的 JavaScript调度程序 DHTMLX Scheduler 是一个 JavaScript 日程安排日历&#xff0c;具有 10 个视图和可定制的界面&#xff0c;用于开发任何类型的日程安排应用程序。 DHTMLX JS 调度程序库的主要特性 我们的 JS 调度程序最需要的功能之一是时间轴视图。借助时间轴…

【语义分割数据集】——imagenet语义分割

地址&#xff1a;https://github.com/LUSSeg/ImageNet-S 1 例图 2. 类别和数量信息 疑问 根据原文的描述&#xff1a;Based on the ImageNet dataset, we propose the ImageNet-S dataset with 1.2 million training images and 50k high-quality semantic segmentation annot…

【JNPF】好用、高性价比的低代码开发平台

目录 1.JNPF介绍 突出优势 2.JNPF的开放性与扩展性 平台的开放性&#xff1a; 平台高拓展性 在快速发展的软件开发领域&#xff0c;低代码平台已经成为了一种重要的开发方法&#xff0c;它使非专业开发人员也能够参与到软件开发中去&#xff0c;大大加速了软件开发的效率。…

Leetcode—2034.股票价格波动【中等】

2023每日刷题&#xff08;五十二&#xff09; Leetcode—2034.股票价格波动 算法思想 实现代码 class StockPrice { public:int last 0;multiset<int> total;unordered_map<int, int> m;StockPrice() {}void update(int timestamp, int price) {if(m.count(time…

VUE学习一、环境的安装

1.node.js安装 node.js是前端依赖的环境, 类似于java中的jdk 下载地址 node.js 下载 msi文件 下完就是一顿嘎嘎安装 , 安装后可以cmd看看node和npm的版本 1.2 yarn的安装 Yarn是Facebook最近发布的一款依赖包安装工具。Yarn是一个新的快速安全可信赖的可以替代NPM的依赖管…

计算机图形学——消隐算法

目录 消隐算法 &#xff08;1&#xff09;隐藏线消除算法 &#xff08;2&#xff09;隐藏面消除算法 曲面体消隐算法 3D Mesh 隐藏面消除算法 &#xff08;1&#xff09;深度缓冲器算法&#xff08;zBuffer&#xff09; 深度缓冲器 &#xff08;2&#xff09;深度排序…

SpringBoot的监控(Actuator) 功能

目录 0、官方文档 一、引入依赖 二、application.yml文件中开启监控 三、具体使用 四、具体细节使用 五、端点开启与禁用 六、定制Endpoint 1. 定制 /actuator/health 2. 定制 /actuator/info &#xff08;1&#xff09;直接在配置文件中写死 &#xff08;2&#xff…

如何进行代码混淆?方法与常见工具介绍

​ 目录 什么是代码混淆&#xff1f; 代码混淆的方法 常见代码混淆工具 什么是代码混淆&#xff1f; 代码混淆是指将计算机程序的代码转换成一种功能上等价&#xff0c;但难于阅读和理解的形式的行为。混淆后的代码很难被反编译&#xff0c;即使反编译成功也很难得出程序的…

【Linux系统化学习】命令行参数 | 环境变量的再次理解

个人主页点击直达&#xff1a;小白不是程序媛 Linux专栏&#xff1a;Linux系统化学习 代码仓库&#xff1a;Gitee 目录 mian函数传参获取环境变量 手动添加环境变量 导出环境变量 environ获取环境变量 本地变量和环境变量的区别 Linux的命令分类 常规命令 内建命令 …

js获取快递单号小练习

目录 1、css代码 2、html代码 3、js代码 完整代码 效果图 1、css代码 .box{width: 400px;height: 300px;margin: 100px auto;position: relative;}input{width: 250px;height: 40px;outline: none;}span{display: block;position: absolute;min-width: 270px;max-width: 40…

pytest +uiautomator2+weditor app自动化从零开始

目录结构1.0 把设备连接单独移出去了 模块操作代码&#xff0c;有一些流程操作和断言方法 from devices import dv from time import sleep import random from tool.jt import capture_screenshotdef initialization(func):def wrapper():sleep(1)dv.app_stop(com.visteon.…

CSS特效025:旋转的loading状态

CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花边是描述了一些CSS…

Linux学习笔记(九)MISC设备驱动

前言 misc 的意思是混合、杂项的&#xff0c;因此 MISC 驱动也叫做杂项驱动。也就是当我们板子上的某些外设无法进行分类的时候就可以使用 MISC 驱动。 MISC 驱动其实就是最简单的字符设备驱动&#xff0c;通常嵌套在 platform 总线驱动中&#xff0c;实现复杂的驱动&#xff0…

Mysql 索引概念回顾

一、什么是索引 在关系数据库中&#xff0c;索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构&#xff0c;它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录&#xff0c;可以根据…

《算法竞赛进阶指南》------图论篇

文章目录 0x01 Telephone Lines POJ - 36620x02 P1073 [NOIP2009 提高组] 最优贸易0x03 道路和航线 BZOJ22000x04 Sorting It All Out POJ - 1094 topo0x05 Sightseeing trip POJ - 1734 最小环问题0x06 Cow Relays POJ - 3613 S到E经过k条边的最短路0x07 走廊泼水节 &#xff…

为什么Java程序员需要掌握多线程?揭秘并发编程的奥秘

为什么Java程序员需要掌握多线程&#xff1f;揭秘并发编程的奥秘 个人简介前言多线程对于Java的意义&#x1f4cc;1.提高程序性能&#xff1a;&#x1f4cc;2 提高用户体验&#xff1a;&#x1f4cc;3支持并发处理&#xff1a;&#x1f4cc;4 资源共享和同步&#xff1a;&#…

C# 语法笔记

1.ref、out&#xff1a;参数传递的两种方式 ref&#xff1a;引用传递 using System; namespace CalculatorApplication {class NumberManipulator{public void swap(ref int x, ref int y){int temp;temp x; /* 保存 x 的值 */x y; /* 把 y 赋值给 x */y temp; /* 把 t…

Python中的range()函数详解:掌握迭代的利器

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Python中的range()函数是一个强大的工具&#xff0c;用于生成一系列的数字&#xff0c;常用于循环操作。虽然看似简单&#xff0c;但其灵活性和功能却不容小觑。在本文中&#xff0c;将深入研究range()函数&…