【Linux】自定义协议——网络计算器实现
📝前言:
这篇文章我们来讲讲Linux——自定义协议,序列化和反序列化
🎬个人简介:努力学习ing
📋个人专栏:Linux
🎀CSDN主页 愚润求学
🌄其他专栏:C++学习笔记,C语言入门基础,python入门基础,C++刷题专栏
目录
- 一,套接字缓冲区
- 二,序列化和反序列化
- 1. jsoncpp
- 2. Json::Value
- 3. Json::FastWriter 和 Json::Reader
- 三,守护进程
- 1. 补充知识
- 2. 作业
- 2.1 作业状态
- 2.2 作业控制
- 3.守护进程
- 四,代码实现
一,套接字缓冲区
- TCP 和 UDP 套接字都有内核维护的缓冲区。当调用
read()
时,数据并非直接发送到网络,而是从用户空间拷贝到套接字的发送缓冲区。 - 当数据拷贝到套接字缓冲区时,内核会帮我们把数据通过网络传送到另一个主机的套接字缓冲区中(也就是说:数据在网络中的实际传输由操作系统内核负责,应用程序无需关心底层细节)
- 再由对方调用
read()
把数据从缓冲区拷贝回他的用户层
注意:因为TCP协议是面向字节流的,所以我们无法确定我们read
得到的是 0.5个/ 1个 / 1.5 个报文,即:我们需要设置分隔符等方法来:确保接受报文的单个完整性
二,序列化和反序列化
- 数据能传:为了使数据传输更方便,我们通常先将数据序列化统一,然后方便网络的传输,另一方收到了以后,再反序列化得到原来的数据。
- 数据能懂:为了确保数据的规范(或者说让对方能知道数据的含义),我们通常会制定协议(即:规定)
1. jsoncpp
安装:sudo apt-get install libjsoncpp-dev
,如果不行,可能是apt-get
没有更新到最新版本,应该先执行:sudo apt-get update
安装好后,头文件在:#include <jsoncpp/json/json.h>
2. Json::Value
Json::Value
本质上就是 JSON 序列化 / 反序列化流程中的 “中间站” 和 “结构化数据容器”,结构化的数据和字符串json都会中途存储在 Jason::Value
中
3. Json::FastWriter 和 Json::Reader
Json::FastWriter
的write
用于序列化Json::Reader
的parse
用于反序列化
注意:server
和client
的序列化和反序列化要处理的数据是不同的
client → server:
client
需要将3+2
表达式序列化,然后传输给server
server
需要将接收到的3+2
反序列化,然后调用cal
计算(业务)
server → client:
server
将得到的结果:5
序列化传输回去client
收到后,反序列化得到5
我们把client
的操作封装到Request
中,把server
的操作封装到Response
中
三,守护进程
1. 补充知识
一些基本概念:
- 进程组:进程是以进程组的形式完成任务的,组长进程的ID和进程组ID一样
- 会话:是多个进程组的集合
- 一个终端创建的时候就有一个会话
- 如果会话销毁了,OS会向里面的进程组发送SIGHUP 信号(挂断信号),即:里面的进程都会销毁
- 会话也有ID(SID)
- 当登陆Xshell的时候,就是创建会话,
bash
进程独立成一组,成为该会话的首进程,并且会打开文件描述符012
问:为什么终端运行了新进程以后,终端就无法响应
ls
等命令。
答:因为键盘只有一个,即:所以一次会话中有且只能有一个前台进程组,占用标准输入。当我们在bash
运行新进程的时候,新进程会继承bash
的文件描述符012
,新进程作为前台进程,此时bash
会被切换到后台,所以不会得到前台的标准输入。
2. 作业
作业:在当前终端会话中启动用来完成某些任务的进程或进程组
2.1 作业状态
2.2 作业控制
-
jobs
:查看作业列表
-
&
:启动时加&
默认到后台运行 -
Ctrl+Z
:挂起,向前台进程组的所有进程发送 SIGTSTP 信号(挂起信号),前台进程组立刻暂停 -
fg
:将作业切回前台
-
bg
:将挂起作业恢复至后台(只能对暂停作业恢复),参数和fg
一样
3.守护进程
终端创建的时候会创建会话,如果终端关了,会话就被销毁了,会话中的进程就会销毁。
和终端切除关联:setsid()
函数
- 为调用进程创建新的会话,并成为该新会话的首进程,与原终端切除关联了
- 调用
setsid()
进程不能是组长进程- 避免进程组组长:先通过
fork()
创建子进程,让父进程退出,再让子进程调用setsid()
(因为有父进程,所以子进程一定不是组长)
- 避免进程组组长:先通过
切断与终端交互:dev/null
文件
- 写入这个文件的内容都会被丢弃,从这个文件里面读到的内容都是空
- 守护进程往往要把
012
给关了,或者重定向,因为守护进程不与终端交互
设计守护进程的系统调用daemon
:
#include <unistd.h>
int daemon(int nochdir, int noclose);
daemon
的核心是setsid()
- 参数
nochdir
:是否保留原工作目录1
:保留0
:不保留,切换到/
目录(推荐)
noclose
:是否保留标准流1
:保留0
,不保留,重定向到dev/null
文件(推荐)
四,代码实现
请访问我的GIthub——Netcal
运行时,查看进程信息,可见TTY → ?(即:关联到任何交互式终端,已为守护进程)
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!