套接字應用程序

這章節是關于實現 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.pswp.cn/news/207410.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207410.shtml
英文地址,請注明出處:http://en.pswp.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 就切換到核心態去執行對應的中斷處理程序…

Android 獲取進程名稱

Android 獲取進程名稱 本篇文章主要獲取下當前應用的進程名稱,具體代碼如下: public static String getProcessNameDevice(final Context context) {int myPid Process.myPid();if (context null || myPid < 0) {return "";}ActivityManager.RunningAppProces…

DHTMLX Scheduler PRO 6.0.5 Crack

功能豐富的 JavaScript調度程序 DHTMLX Scheduler 是一個 JavaScript 日程安排日歷&#xff0c;具有 10 個視圖和可定制的界面&#xff0c;用于開發任何類型的日程安排應用程序。 DHTMLX JS 調度程序庫的主要特性 我們的 JS 調度程序最需要的功能之一是時間軸視圖。借助時間軸…

vue-loader是如何工作的?

什么是單文件組件&#xff1f; 單文件組件是一種將模板、腳本和樣式封裝在一個 .vue 文件中的方式 例如&#xff1a; <template><div class"example">{{ msg }}</div> </template> <script>export default {data() {return {msg: &qu…

【語義分割數據集】——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;大大加速了軟件開發的效率。…

2023年總結和2024年展望(以ue為主攻)

2023年就要過去了&#xff0c;總結下&#xff1a; 先說好的地方 1&#xff0c;pbr材質集成到了osg中&#xff0c;加上直接光和間接光。終于知道pbr咋回事了。光線追蹤的視頻也跟著敲了一個。 2&#xff0c;得到了認可。拿到了半年獎&#xff0c;leader讓我明年和架構師一起進行…

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…

分頁顯示功能函數的核心 代碼主要參考思路

分頁顯示功能函數的核心 代碼主要參考思路 package org.utils;import java.util.List;import org.entity.Student;/*** * author 24519* 分頁的工具類**/ public class PageUtils {//頁大小&#xff08;每頁顯示多少條記錄&#xff09;private int pageSize;//當前頁private in…

如何進行代碼混淆?方法與常見工具介紹

? 目錄 什么是代碼混淆&#xff1f; 代碼混淆的方法 常見代碼混淆工具 什么是代碼混淆&#xff1f; 代碼混淆是指將計算機程序的代碼轉換成一種功能上等價&#xff0c;但難于閱讀和理解的形式的行為。混淆后的代碼很難被反編譯&#xff0c;即使反編譯成功也很難得出程序的…

【Linux系統化學習】命令行參數 | 環境變量的再次理解

個人主頁點擊直達&#xff1a;小白不是程序媛 Linux專欄&#xff1a;Linux系統化學習 代碼倉庫&#xff1a;Gitee 目錄 mian函數傳參獲取環境變量 手動添加環境變量 導出環境變量 environ獲取環境變量 本地變量和環境變量的區別 Linux的命令分類 常規命令 內建命令 …

前端面試JS—map 和 forEach 的區別

目錄 相同點&#xff1a; 不同點&#xff1a; 相同點&#xff1a; 都是循環遍歷數組中的每一項&#xff08;接收一個函數作為參數&#xff0c;并對每個數組元素執行一次&#xff09;每次執行匿名函數都支持三個參數&#xff1a;&#xff08;三個參數分別為item&#xff08;當前…

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…

Ubuntu 修改當前用戶的名稱

UBUNTU 2018.04 LTS 64位 修改當前用戶的名稱 操作步驟如下&#xff1a; 假設你的帳號AAA &#xff0c; 打算修改為BBB。開機進入桌面。按下ctrl alt F1~F7 三個組合鍵。功能鍵F1到F7任選1個。 進入黑屏。登陸root 用戶&#xff0c;進入后。修改以下三個文件 /etc/passwd&a…