当前位置: 首页 > news >正文

【Linux】序列化与反序列化、会话与进程组、守护进程

一.序列化和反序列化

协议其实就是结构化的数据。但是再网络通信中,我们不直接发送结构化的数据给对方。我们一般会将结构化的数据序列化成字符串/字节流,然后通过网络在发送出去。而接收方收到之后,要对收到的字符串/流式数据进行反序列化,即还原成结构化的样子。

那么我们可以直接发送二进制对象么,这个结构化数据双方都能认识啊?

可以,但不建议。

可以是因为在操作系统内部,协议都是直接传递的结构体,因为所有的操作系统都是C语言写的。不会存在差异。

不建议是因为通信双方可能是不同的语言实现的,这导致它们对结构体的对齐规则可能有差异。导致接受的数据可能不完整。

二.使用jsoncpp库实现序列化和反序列化

1.序列化

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>int main()
{Json::Value root;root["name"] = "zhangsan";root["age"] = 18;root["sex"] = "man";// 1. 使用root.toStyledString()序列化std::string s1 = root.toStyledString();std::cout << s1 << std::endl;// 2. 使用StyledWriter对象的write方法进行序列化Json::StyledWriter writer;std::string s2 = writer.write(root);std::cout << s2 << std::endl;// 3. 使用FastWriter对象的write方法进行序列化Json::FastWriter wr;std::string s3 = wr.write(root);std::cout << s3 << std::endl;// 4. 使用StreamWriterBuidler 对象new一个witer对象// 通过new出来的对象,将root数据,写入到一个字符串流中Json::StreamWriterBuilder swb;std::unique_ptr<Json::StreamWriter> wri(swb.newStreamWriter());std::stringstream ss;wri->write(root, &ss);std::cout << ss.str() << std::endl;return 0;
}

2.反序列化 

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>int main()
{Json::Value root;root["name"] = "zhangsan";root["age"] = 18;root["sex"] = "man";// 1. 使用root.toStyledString()序列化std::string s1 = root.toStyledString();std::cout << s1 << std::endl;// 2.反序列化Json::Reader reader;reader.parse(s1, root);std::string name = root["name"].asString();int age = root["age"].asInt();std::string sex = root["sex"].asString();std::cout << "name->" << name << std::endl;std::cout << "age->" << age << std::endl;std::cout << "sex->" << sex << std::endl;
}

三.tcp支持全双工 

我们进行tcp socket编程时,是直接使用read、write接口使用sockf进行读写的。而且我们读写都使用的是同一个文件描述符。这也就说明了tcp是支持全双工的。这是因为tcp内部有两个缓冲区---接收缓冲区和发送缓冲区。

而read和write并不是直接将数据写入到网络中的,而是先将数据发送到发送缓冲区中,最后由tcp协议决定什么时候将缓冲区的数据发送到网络中。write也不是直接从网络中读,而是从接收缓冲区中读。

在发送数据的时候,tcp(传输控制协议)自主决定,什么时候发,发多少,出错了怎么办。

主机间通信的本质:把发送方的发送缓冲区内部的数据,拷贝到对端的接收缓冲区。 

四.会话

1.进程组 

进程是以进程组的方式来完成作业的。进程组是一个或多个进程的集合。

我们启动了一个sleep 1000 | sleep 2000 | sleep 3000 & 的后台程序。而这三个进程就组成了一个进程组。

 进程组id就是该进程组的组长id,也就是组长id的pid。

2.会话

而SID就是会话。当我们登录的时候,打开终端,ssh会为我们打开0,1,2文件描述符,然后进行程序替换,让bash运行。一登录终端,就会创建一个会话,此时会话中只有一个进程组,该进程组中只有一个bash进程。

一个会话内部会存在多个进程组。

 五.守护进程

我们目前运行的程序都是直接在当前会话中启动的。并且都是只有一个进程的进程组。而该进程是受用户终端的登录状态影响的。当我们退出登录,就会销毁会话,会话中的进程就有可能被影响。

对于服务器来说,作为一个常驻内存的进程,不应该受用户的登录和退出状态所影响。

为了避免登录和注销的影响,我们需要将进程进行守护进程化。

守护进程即该进程拥有一个独立的会话,并且再后台运行。

 使用setsid来使进程,守护进程化。

NAMEsetsid - creates a session and sets the process group IDSYNOPSIS#include <sys/types.h>#include <unistd.h>pid_t setsid(void);

setsid要求调用该函数的进程不能是进程组的组长。(进程组的组长退出了,进程组并不会销毁,直到该进程组中所有的进程都退出了,进程组才消失)。

所以,我们可以采取fork子进程,并让父进程直接退出,让子进程执行setsid。

当然,我们也可以使用库里面的方法,实现守护进程化。

nochdir:是否将当前的工作目录转换为根目录

noclose:是否将0,1,0重定向到/dev/null文件,从该文件读只会读到null,写入该文件的内容都会被丢弃

NAMEdaemon - run in the backgroundSYNOPSIS#include <unistd.h>int daemon(int nochdir, int noclose);

下面是实现守护进程化的具体操作。  

#pragma once #include <iostream>
#include <string>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>const std::string cwd = "/";
const std::string dev = "/dev/null";// 让网络服务器守护进程化
// 让启动的进程,独立成为一个进程组,并且占有独立的会话
// 守护进程化要求该进程不能是进程组的组长
void Daemon(int nochdir, int noclose)
{// 1. 守护进程忽略IO,以及子进程退出等相关信号signal(SIGPIPE, SIG_IGN);signal(SIGCHLD, SIG_IGN);// 2.必须得是一个进程组的组员,不能是组长if(fork() > 0) exit(0);// 下面就是子进程,也就是组员进程// 2.5 守护进程话setsid();// 3.守护进程执行时需要将其当前的工作目录改为/根目录if(nochdir == 0) chdir(cwd.c_str());// 4.守护进程本质上是一个孤儿进程,后台进程// 要避免其使用0,1,2与终端交互// 所以,将0,1,2重定向到/dev/null文件,该文件会将写入的内容丢弃,从该文件读,会读到nullptrif(noclose == 0){int fd = open(dev.c_str(), O_RDWR); // 以读写方式打开// 重定向// int dup2(int oldfd, int newfd); // dup2会使用oldfd,覆盖newfddup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);}
}

相关文章:

  • Fabric 服务端插件开发简述与聊天事件监听转发
  • 【C++ 基础数论】质数判断
  • AI大模型中系统化的KV Cache加速方案,减少KV Cache显存占用的优化方法
  • AI推介-大语言模型LLMs论文速览(arXiv方向):2024.11.25-2024.11.30
  • 【打破信息差】萌新认识与入门算法竞赛
  • QBasic 一款古老的编程语言在现代学习中的价值(附程序)
  • 刷leetcodehot100返航版--双指针5/16
  • 西安前端面试
  • 机器学习中的特征工程:解锁模型性能的关键
  • 计算机组成原理——数据的表示
  • 代码随想录 算法训练 Day3:链表1
  • 隧道结构安全在线监测系统解决方案
  • 从裸机开发到实时操作系统:FreeRTOS详解与实战指南
  • 英飞凌TLE9945GPT12
  • SSH主机密钥验证失败:全面解决方案与技术手册
  • 【言语】刷题5(填空)
  • MySQL数据库——支持远程IP访问的设置方法总结
  • 【RabbitMQ】消息丢失问题排查与解决
  • 将单链表反转【数据结构练习题】
  • (for 循环) VS (LINQ) 性能比拼 ——c#
  • 世界数字教育大会发布“数字教育研究全球十大热点”
  • 上海比常年平均时间提前12天入夏,明天最高气温可达33℃
  • 董军在第六届联合国维和部长级会议上作大会发言
  • 申论|空间更新结合“青银共生”,助力青年发展型城区建设
  • 秘鲁总统任命前司法部长阿拉纳为新总理
  • 遭“特朗普关税”冲击,韩国今年经济增长预期“腰斩”降至0.8%