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

【linux】再谈网络基础(一)

1. 再谈 "协议"

协议是一种 "约定",在读写数据时, 都是按 "字符串" 的方式来发送接收的.

但是这里我们会遇到一些问题:

如何确保从网上读取的数据是否是完整的,区分缓冲区中的由不同客户端发来的数据

2. 网络版计算器

举例:我们需要实现一个服务器版的加法器. 我们需要客户端把要计算的两个加数发过去, 然后由服务器进行计算, 最后再把结果返回给客户端

约定方案一:

客户端发送一个形如"1+1"的字符串;

这个字符串中有两个操作数, 都是整形;

两个数字之间会有一个字符是运算符, 运算符只能是 + ;

数字和运算符之间没有空格;

结果:不可取,无法判断从网上读取的数据是否是完整的

约定方案二:

定义结构体来表示我们需要交互的信息;

发送数据时将这个结构体按照一个规则转换成字符串(这个过程叫做 "序列化"), 接收到数据的时候再按照相同的规则把字符串转化回结构体;(这个过程叫做“反序列化”)

自定义序列化,反序列化

#include<iostream>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string>
#include<memory>
#include<unistd.h>
using namespace std;
#include"head.hpp"
class sock
{
public:sock(uint16_t port = 8080):_port(port){}void Init(){fd = socket(AF_INET,SOCK_STREAM,0);if(fd < 0){cout << "socket fail" << endl;exit(1);}}void Bind(){sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(_port);addr.sin_addr.s_addr = inet_addr("0.0.0.0");socklen_t len = sizeof(addr);int n = bind(fd,(struct sockaddr*)&addr,len);if(n < 0){cout << "bind fail" << endl;exit(2);}}void Listen(){int n = listen(fd,0);if(n < 0){cout << "listen fail" << endl;exit(3);}}void Accept(int &client_fd){sockaddr_in addr;socklen_t len = sizeof(addr);client_fd = accept(fd,(struct sockaddr*)&addr,&len);if(client_fd < 0){cout << "accept fail" << endl;}else{cout << "get a new link ..." << endl;}}int  Connect(const uint16_t& port,const string &s){sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(s.c_str());socklen_t len = sizeof(addr);int n = connect(fd,(struct sockaddr*)&addr,len);if(n < 0){cout << "connect fail" << endl;exit(4);}return fd;}
private:int fd;uint16_t _port;
};
#include<string>
string package(const string &content)
{//len\ncontent\nint n = content.size();string s = to_string(n);s += '\n';s += content;s += '\n';return s;
}
string prase(string &package)
{//len  \n  content  \nsize_t pos = package.find('\n');if(pos == string :: npos){return nullptr;}int len_package = package.size();string l = package.substr(0,pos);int len = stoi(package.substr(0,pos));if(l.size() + 2 + len > len_package){return nullptr;}string s;s = package.substr(pos + 1,len);package.erase(0,l.size() + 2 + len);return s;}
struct protocol_client
{protocol_client(int x = 0,int y = 0,char op = '+'):_x(x),_y(y),_op(op){}string serialize(){// _x _op _ystring s;s += to_string(_x);s += " ";s += _op;s += " ";s += to_string(_y);return s;}void deserialize(const string &s){int left = s.find(' ');if(left == string :: npos){cout << "protocol_client : find fail" << endl;}int right = s.rfind(' ');if(right == string :: npos){cout << "protocol_client : find fail" << endl;}if(left + 2 != right){cout << "protocol_client : deserialize fail" << endl;return ;}_x = stoi(s.substr(0,left));_y = stoi(s.substr(right + 1));_op = s[left + 1];}int _x;int _y;char _op;
};
struct protocol_server
{protocol_server(int result = 0,int code = 0):_code(code), _result(result){}string serialize(){//_result _codestring s;s += to_string(_result);s += " ";s += to_string(_code);return s;}void deserialize(const string &s){size_t pos = s.find(" ");if(pos == string :: npos){cout << "protocol_client : find fail" << endl;}_result = stoi(s.substr(0,pos));_code = stoi(s.substr(pos + 1));}int _code;
int _result;
};
#include"server.hpp"
int main()
{unique_ptr<server> sv(new server());sv->start();sv->run();return 0;
}
#include "sock.hpp"
#include"protocol.hpp"
class server
{
public:server(){}void start(){svr.Init();svr.Bind();svr.Listen();}void run(){int client_fd;svr.Accept(client_fd);string e;while(true){//读端char buff[1024];ssize_t n = read(client_fd, buff, sizeof(buff));if (n < 0){cout << "server : read fail" << endl;}buff[n] = 0;e += buff;string s = prase(e);protocol_client sv;sv.deserialize(s);//计算int result,code = 0;switch(sv._op){case '+':result = sv._x + sv._y;break;case '-':result = sv._x - sv._y;break;case '*':result = sv._x * sv._y;break;case '/':if(sv._y == 0){code = 1;}else{result = sv._x / sv._y;}break;default:code = 2;}protocol_server ss(result,code);s = ss.serialize();s = package(s);//写端n = write(client_fd,s.c_str(),s.size());if(n < 0){cout << "server : write fail" << endl;}}}
private: sock svr;
};
#include"sock.hpp"
#include"protocol.hpp"
void usage()
{cout << "x + y = ? " << endl;
}int main()
{uint16_t port = 8080;sock client;client.Init();int fd = client.Connect(port,"1.94.49.66");string e;while(true){usage();int x,y;char op;//写端cout << "please enter: x >   ";cin >> x;cout << "please enter: op >   ";cin >> op;cout << "please enter: y >   ";cin >> y;protocol_client sv(x,y,op);string s = sv.serialize();s = package(s);ssize_t n = write(fd,s.c_str(),s.size());if(n < 0){cout << "client : write fail" << endl;}//读端char buff[1024];n = read(fd,buff,sizeof(buff));if(n < 0){cout << "client : read fail" << endl;}buff[n] = 0;e += buff;s = prase(e);  protocol_server ss;ss.deserialize(s);cout << "result : " << ss._result << "    code : " << ss._code << endl;cout << "-------------------------------------------------------------" << endl << endl;}return 0;
}

 json类

#include<jsoncpp/json/json.h>
int main()
{Json::Value root;root["x"] = 100;root["y"] = 200;root["op"] = '+';root["dect"] = "this is a + oper";Json::FastWriter w;string res = w.write(root);cout << res << endl;return 0;
}
Json::Value v;
Json::Reader r;
r.parse(res,v);
int x = v["x"].asInt();
int y = v["y"].asInt();
char op = v["op"].asInt();
string dect = v["dect"].asString();

3. HTTP协议

(一)认识 HTTP协议

应用层协议是我们程序员自己定的,但实际上, 已经有一些现成的, 又非常好用的应用层协议, 供我们直接参考使用,如 HTTP(超文本传输协议) 就是其中之一.

(二)认识URL

平时我们说 "网址" 就是URL

注意:

  1. 像网站这种,一般默认会添加协议方案名,且协议方案名对应唯一一个端口号,所以即使不写端口号,也没关系(如:http 对应端口号 80,https 对应端口号 443)
  2. web根目录不一定是linux系统下的根目录,具体指什么,完全由服务器那边解释

(三)urlencode(编码) 和 urldecode(解码)

像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现

所以,如果某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

转义的规则如下(这个过程叫编码):

将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式

编码解码工具:

URL 编码解码 - Codeeeee 在线小工具

4. HTTP协议格式

注意:

  1. 上图对应格式是打印出来的格式,实际上,发送到网络上的是整个字符串,是连在一起的
  2. http也是一种协议,它也需要将数据序列化,反序列化

代码

5. HTTP的方法

其中最常用的就是 GET方法 和 POST方法

注意:

  1. GET 方法 和 POST 方法都可以传参
  2. GET 方法的参数是在 url 内的,通过 url 提交的,POST 方法的参数是在正文内
  3. POST 方法 比 GET 方法更加私密

GET 方法:

POST 方法:

6. HTTP的状态码

最常见的状态码, 比如 200(OK), 404(Not Found,一般是客户端要访问的文件不存在), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)

注意:

  1. 3XX代表的重定向有两种:一种是临时移动,另一种是长期移动
  2. 长期移动:一旦设置了永久重定向,所有后续对原始URL的请求都应该被自动转发到新的URL,而且这个重定向是长期有效的;临时移动:表明资源的移动是暂时的。 客户端在接收到临时重定向响应后,会临时使用新的URL,但在将来的某个时间点,对原始URL的请求可能会恢复为直接访问原始资源,而不是被重定向

HTTP常见Header

Content-Type: 数据类型(text/html等)

Content-Length: Body的长度

Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;

User-Agent: 声明用户的操作系统和浏览器版本信息;

referer: 当前页面是从哪个页面跳转过来的;

location: 搭配3xx状态码使用, 告诉客户端接下来要去哪里访问;

Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能

注意:

  1. Content-Type : 指明访问的路径是什么类型(如:.html : 网页 ; .jpg :jpg格式的图片 ;.png : png格式的图片 ...... )
  2. Cookie : Cookie文件可能是内存级的(储存在内存里),也可能是文件级的(储存在磁盘里)

  1. cookie文件的内容保存多久,一般是由浏览器决定的,如果内容没有了,则下一次访问对应服务器,仍要进行验证
  2. http协议默认是无状态的
  3. http对登入用户的会话保持功能

7. 长连接和短连接

  1. 即使是一个网页,也可能包含很多元素,每一个元素,都要进行一次http请求,即建立一个tcp连接,就会发生多个请求和响应,这就是长连接
  2. 只有一次请求和响应,连接就断开的,就是短连接

相关文章:

【linux】再谈网络基础(一)

1. 再谈 "协议" 协议是一种 "约定"&#xff0c;在读写数据时, 都是按 "字符串" 的方式来发送接收的. 但是这里我们会遇到一些问题&#xff1a; 如何确保从网上读取的数据是否是完整的&#xff0c;区分缓冲区中的由不同客户端发来的数据 2. 网…...

Unknown at rule @tailwindscss(unknownAtRules)

一、前言 整合 tailwindcss 后&#xff0c;发现指令提示警告 Unknown at rule tailwindscss(unknownAtRules)&#xff0c;其实是 vscode 无法识别 tailwindscss 指令&#xff0c;不影响使用&#xff0c;但是对于我这种有编程洁癖的人来说&#xff0c;有点膈应。 二、解决方案…...

IDEA - 快速去除 mapper.xml 黄色警告线和背景色----简化版

1.打开设置 2.去掉黄色警告线设置 3.去掉背景色设置 4.示范图...

高级 SQL 技巧详解

文章目录 高级 SQL 技巧详解一、引言二、窗口函数1、窗口函数的使用1.1、RANK() 函数示例1.2、常用窗口函数 三、公共表表达式&#xff08;CTE&#xff09;2、CTE 的使用2.1、CTE 示例 四、索引优化3、索引的创建与优化3.1、创建索引3.2、索引类型与注意事项 五、事务管理4、事…...

移除元素(java)

给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k&#xff0c;要通过此题&#xff0c;您需要执行以下操作&#xff1a; 更改…...

【Linux】shell脚本:检测文件是否存在,如存在则删除

通常&#xff0c;可以使用[ -f <file> ]来检查文件是否存在&#xff0c;使用rm <file>来删除文件。 以下是一个示例脚本&#xff0c;用于检测一个文件是否存在&#xff0c;并在存在时删除它&#xff1a; #!/bin/bash # 定义要检查的文件路径 file_path"/…...

Git代码托管(三)可视化工具操作(1)

常见的可视化操作工具有 一、官方网页 如码云、gitlab&#xff0c;自带了常见的git操作。 以码云为例&#xff1a; 1、创建分支&#xff1a; 进入分支目录&#xff0c;点击 新建分支 按钮&#xff0c; 在弹出框中输入新分支名称&#xff0c;点击确定即可一键创建分支&…...

How to use ffmpeg to convert video format from .webm to .mp4

The .mp4 container format doesn’t support the VP8 codec, which is commonly used in .webm files. MP4 containers typically use the H.264 codec for video and AAC for audio. You’ll need to re-encode the video using the H.264 codec and re-encode the audio us…...

Halcon 从XML中读取配置参数

1、XML示例 以下是一个XML配置文件的示例,该文件包含了AOI(自动光学检测)算法的环境参数和相机逻辑参数: <AOI><!--AOI算法参数 20241106--><Env><!--环境参数--><Param name="GPUName" value="NVIDIA GeForce RTX 405…...

hive表内外表之间切换

你想把内表和外表在元数据上达到切换的目的&#xff0c;这个操作有个前提&#xff0c;在apache版本源码上来讲是支持的&#xff01;&#xff01;&#xff01;&#xff01;但是&#xff01;&#xff01;&#xff01;&#xff01;注意哦&#xff01;默认情况下apache版本的源码中…...

电子邮件营销软件哪个好?

在数字化时代&#xff0c;电子邮件营销仍然是企业与客户沟通的核心策略之一。无论是推广新产品、发送新闻简报&#xff0c;还是进行客户关系管理&#xff0c;选择合适的电子邮件营销软件至关重要。面对市场上众多的选择&#xff0c;企业如何才能找到最适合自己的工具呢&#xf…...

OpenAI大事记;GPT到ChatGPT参数量进化

目录 OpenAI大事记 GPT到ChatGPT参数量进化 OpenAI大事记 GPT到ChatGPT参数量进化 ChatGPT是从初代 GPT逐渐演变而来的。在进化的过程中,GPT系列模型的参数数量呈指数级增长,从初代GPT的1.17亿个参数,到GPT-2的15 亿个参数,再到 GPT-3的1750 亿个参数。模型越来越大,训练…...

springboot020基于Java的免税商品优选购物商城设计与实现

&#x1f345;点赞收藏关注 → 文档最下方联系方式领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345; 一 、设计说明 1…...

代码随想录之字符串刷题总结

目录 1.反转字符串 2.反转字符串II 3.替换数字 4.翻转字符串里面的单词 5.右旋&&左旋字符串 1.反转字符串 题目描述&#xff1a; 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。 不要给另外的数组分配额外…...

PS-基础学习(常用快捷键1.2-1.3)

常用快捷键 钢笔操作功能Alt 选择工具使用选择工具放到锚点上&#xff0c;按下alt&#xff0c;然后放到调整曲度的上面&#xff0c;可以修改一边的曲度可以修改出不平滑的转折点选择工具放到锚点上进行拖拽可以移动锚点的位置ctrl 选择工具使用选择工具&#xff0c;按住ctrl…...

qt QListView详解

1、概述 QListView 是 Qt 框架中的一个视图类&#xff0c;用于展示模型中的数据。它基于 QAbstractItemView&#xff0c;支持多种视图模式&#xff0c;如列表视图&#xff08;List View&#xff09;、图标视图&#xff08;Icon View&#xff09;等。QListView 是模型/视图框架…...

287. 寻找重复数

目录 题目我的解法解法 题目 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返回 这个重复的数 。 你设计的解决方案…...

2024年最受欢迎的编程语言

No.1 JavaScript / TypeScript 自从创建第一个网站以使其动态化以来&#xff0c;JavaScript多年来一直受到欢迎。话虽如此&#xff0c;目前JavaScript是整个市场上需求量最大的编程语言。此外&#xff0c;TypeScript&#xff08;一种具有类型安全性的JavaScript超集&#xff0…...

C++ 线程初始化编译报错

这是一个很简单的开启一个线程, 用于演示一个线程和生命周期之间的错误,但是还没有把这个错误暴露出来, 就遇见了一个编译问题. 线程中执行指定逻辑的代码 线程的执行方法, 声明写在了ThreadRun.h 实现写在 ThreadRun.cpp中. class ThreadRun { public: void func(); };void T…...

[MySQL]视图

视图是什么 视图&#xff08;View&#xff09;是一种虚拟存在的表。视图中的数据&#xff0c;来自定义视图的查询语句中&#xff0c;使用的表&#xff0c;并且是在使用视图时动态生成的。 简单讲&#xff0c;视图只保存了查询的SQL逻辑&#xff0c;不保存查询结果。所以我们在…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...