C++ Webserver从零开始:基础知识(一)——Linux网络编程基础API
目录
前言
一.socket地址API
1.主机字节序和网络字节序
2.通用socket地址
3.专用socket地址
二.创建socket
三.绑定socket(命名socket)
四.监听socket
五.接受连接(服务端)
六.发起连接(客户端)
七.关闭连接
八.数据读写
九.一些废话
前言
本专栏将从零开始制作一个C++ Webserver,用以记录笔者学习的过程
如果你想要跟着我这个专栏制作一个C++ Webserver,你需要掌握以下前置基础课程知识:
1.C/C++的语法(在Leetcode刷100~200题的程度即可)
2.计算机网络基础知识
3.操作系统基础知识
掌握以上前置课程知识后,即可开始本专栏的内容
一.socket地址API
1.主机字节序和网络字节序
我们知道,一个32位计算机的CPU累加器一次能累加4字节的数据,而这4字节的数据在内存中排列的顺序是可以有2种方式的,即大端字节序和小端字节序
大端字节序:一个整数的高位字节(23~31bit)存储在内存的低地址处
小端字节序:一个整数的低位字节(0 ~ 7 bit)存储在内存的低地址处
由于不同的主机使用的字节序可能不同,因此两个主机之间发送数据可能会发生错误。解决方法是:
人们制定一个规范:发送端统一使用大端字节序(因此大端字节序称为网络字节序)
而因为现代PC大多采用小端字节序,因此小端字节序称为主机字节序
Linux中实现主机字节序和网络字节序的函数:
#include<netinet/in.h>
unsigned long int htonl(unsigned long int hostlong);
unsigned short int htons(unsigned short int hostshort);
unsigned long int ntohl(unsigned long int netlong);
unsigned short int ntohs(unsigned short int netshort);
他们的作用可以通过名字理解,比如 htonl :" host to network long" ,即长整型的主机字节序转换成网络字节序。这四个函数中long类型的函数一般用来转换IP地址,short类型的一般用来转换端口号(操作系统基础知识)。
2.通用socket地址
主机之间的通信需要知晓对方的地址,而网络中主机的地址是TCP/IP协议族来定义的(计算机网络基础知识),在Linux网络编程中,我们通过使用socket的这个套接字来进行网络通信。socket定义了一系列的API实现网络通信,是非常方便好用的工具。
在socket网络编程中表示地址的是结构体sockaddr,但由于这个结构体的设计问题,无法容纳多数协议族的地址值,因此Linux定义了一个新的通用socket地址结构体
#include<bits/socket.h>
struct sockaddr_storge
{sa_family_t sa_family;unsigned long int __ss_align;char__ss_padding[128-sizeof(__ss_align)];
}
3.专用socket地址
以上两种通用socket地址其实并不好用,所以Linux为各个协议族提供了专门的socket地址结构体
其中,UNIX本地协议族使用sockaddr_un,本文不予说明
而TCP/IP协议族使用sockaddr_in和sockaddr_in6两个分别对应IPv4和IPv6

但需要注意的是,使用sockaddr_in或其他专用socket地址(包括socket_storge),最后都要强制转换成通用socket地址类型sockaddr,这是因为所有socket编程接口使用的地址参数的类型都是sockaddr
二.创建socket
我们了解socket地址API后,要如何创建一个socket呢?下面是创建socket的代码
#include<sys/types.h>
#include<sys/socket.h>
int socket(int domain,int type, int protocol);
int socket(int domain,int type,int protocol);
- 功能:创建一个套接字
- 参数:
- domain:协议族
- AF_INET:IPv4
- AF_INET6:IPv6
- AF_UNIX,AF_LOCAL:本地套接字通信
- type:通信过程中使用的协议类型
- SOCK_STEAM:流式协议(传输层使用TCP协议)
- SOCK_DGRAM:报式协议(传输层使用UDP协议)
- protoco:具体的一个协议,写 0 就行
- 返回值:返回文件描述符,操作内核缓冲区
- 失败:-1
以上块引用中,在写Webserver时都是用笔者加粗部分的参数
另外:
type参数中还可以与以下两个参数相与计算:
SOCK_NONBLOCK:创建的socket为非阻塞
SOCK_CLOEXEC:用fork调用创建子进程时,在子进程中关闭该socket
三.绑定socket(命名socket)
在创建socket时,我们在第一个参数时给它指定了协议族,但是并未指定使用协议族中哪个具体的socket地址。所以我们用系统调用bind来给socket绑定地址。
PS:服务端需要绑定,客户端不需要绑定,客户端采用匿名绑定,操作系统会代劳。
#include<sys/types.h>
#include<sys/socket.h>
int bind(int sockfd,const struct sockaddr* my_addr,socklen_t addrlen);
- 功能:将my_addr所指的socket地址分配给未命名的socket文件描述符
- 参数
- sockfd:通过socket函数得到文件描述符
- addr:需要绑定的socket地址,这个地址封装了ip和端口号的信息
- addrlen:第二个参数结构体占的内存大小
- 返回值
- 0:成功
- -1:失败
四.监听socket
现在我们创建好了socket,也为其分配好了socket地址,接下它就可以工作进行主机间的通信了吗?其实并不行,我们还需要为他创建一个监听队列,用以存储待处理的客户连接。
以下是创建监听队列的系统调用
#include<sys/socket.h>
int lsiten(int sockfd,int backlog);
int listen(int sockfd,int backlog);
- 功能:监听socket上的连接
- 参数
- sockfd:通过socket()函数得到文件描述符
- backlog:未连接的和已经连接的和的最大值
- 返回值:
- 成功:0
- 失败:-1
五.接受连接(服务端)
现在我们已经有了一个监听socket(执行过listen调用,处于LISTEN状态的socket),我们终于可以进行通信啦!而最后一步,就是将监听队列中的一个socket取出来,即可与远端的主机进行读写交互了
下面是从监听队列取出socket的系统调用
#include<sys/types.h>
#include<sys/socket.h>
int accept(int sockfd, struct sockaddr* addr,socklen_t* addrlen);
- 功能:接受客户端连接,默认时一个阻塞的函数,阻塞等待客户端连接
- 参数
- sockfd:用于监听的文件描述符
- addr:传出参数,记录连接成功后客户端的地址信息
- addrlen:指定第二个参数的对应的内存大小
- 返回值:
- 成功:返回用于通信的文件描述符
- 失败:-1
六.发起连接(客户端)
注意,上文的绑定socket,监听socket和接受连接都是服务端要干的事,接下来讲客户端的任务。在服务端创建好了监听队列后,就可以接受来自客户端的连接请求,那么客户端是怎么发起连接请求的呢?
#include<sys/types.h>
#include<sys/socket.h>
int connect(int sockfd,const struct sockaddr* serv_addr,socklen_t addr_len);
- 功能:客户端连接服务器
- 参数
- sockfd:用于通信的文件描述符
- serv_addr:客户端要连接的服务器地址信息
- addrlen:指定第二个参数的对应的内存大小
- 返回值:
- 成功:0
- 失败:-1
七.关闭连接
通信完成后,如要关闭连接,可以通过下面的系统调用
#include<unistd.h>
int close(int fd);
fd参数是待关闭的socket,close系统调用不会立刻关闭一个连接,而是将fd的引用计数-1,只有当其引用计数为0时才会真正关闭连接(类似C++的智能指针)。
在多进程程序中,一次fork系统调用默认将引用计数+1.
如果你非要立即终止连接,也有办法,即shutdown系统调用,读者可以自行搜索。
八.数据读写
我们在二到七的过程中完整经历了socket通信的创建,命名,监听,接受(发起),关闭的过程,在连接建立成功到关闭连接的这个时间段中我们就可以进行两个主机之间的通信。
通信的方式即:
1.发送信息
2.接受信息
专业的说法也就是数据读写。Linux本身对文件的读写也可以用于socket,因为socket本身也是文件(Linux中万物皆文件)。但socket还是提供了几种好用的数据读写系统调用。
分别有
1.TCP数据读写
2.UDP数据读写
3.通用数据读写
本文只介绍TCP数据读写,UDP和通用数据读写请读者自行学习
#include<sys/types.h>
#include<sys/socket.h>
ssize_t recv(int sockfd,void* buf,size_t len,int flags);
ssize_t send(int sockfd,const void* buf,size_t len,int flags);
- 功能:数据读写
- 参数:
- sockfd:用于通信的文件描述符
- buf: 缓冲区的位置
- len:缓冲区的大小
- flags:通常取0,其他含义自行搜素,可以进行具体的控制
- 返回值:
- 成功:
- recv:返回实际读到的数据的长度,如果小于期望长度len就多调用几次recv
- send:实际写入的数据长度
- 失败:-1
九.一些废话
前面一到八即Linux网络编程基础API的常用内容了,其他的一些不常用的API如地址信息函数,socket选项等没有写入文中,一是因为其使用场景较少,二是我对这个专栏的定位是:
简洁且重要
我写的内容基本上是完成C++ Webserver所必须掌握的前置知识,所以会极可能的少,这样的话对一些没有基础却又无从下手的后辈能起到一个引入门的作用。
等真正地了解了这些内容后,再去提升应该会容易的多。之所以这也想是因为我在学习完C/C++,操作系统,计算机网络之后进行项目制作时发现根本无从下手,我在网上找到的内容很少有建立在你完全不了解任何Webserver的知识,但又学完了基础课程的情况下。所以我希望能写一些内容,对和我一样的同学有些帮助。
另外就是我也是在学习过程中,所以想记录一下学习过程帮自己更好地完成这个目标。如果本文有什么问题,或者你有什么建议的话欢迎私信笔者,我看到了应该都会回复。
相关文章:
C++ Webserver从零开始:基础知识(一)——Linux网络编程基础API
目录 前言 一.socket地址API 1.主机字节序和网络字节序 2.通用socket地址 3.专用socket地址 二.创建socket 三.绑定socket(命名socket) 四.监听socket 五.接受连接(服务端) 六.发起连接(客户端) 七.关闭连接…...
cookie和session的工作过程和作用:弥补http无状态的不足
cookie是客户端浏览器保存服务端数据的一种机制。当通过浏览器去访问服务端时,服务端可以把状态数据以key-value的形式写入到cookie中,存储到浏览器。浏览器下次去服务服务端时,就可以把这些状态数据携带给服务器端,服务器端可以根…...
【蓝桥杯选拔赛真题30】C++字母转换 第十三届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析
目录 C/C++字母转换 一、题目要求 1、编程实现 2、输入输出...
资产负债表#通俗易懂
资产负债表(the Balance Sheet)亦称财务状况表,表示企业在一定日期(通常为各会计期末)的财务状况(即资产、负债和业主权益的状况)的主要会计报表。 (99 封私信 / 11 条消息) 能通俗易懂的给小白…...
PCF8563转STM32 RTC避坑指南
问题一,时间读取错误 原因,读写时间必须Time在前,Date在后 HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BCD); HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BCD); HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BCD); …...
前端重置密码报错记录
昨天晚上,我写了重置密码的前端,测试的时候报错 今天上午,我继续试图解决这个问题,我仔细检查了一遍,前端没有问题 可以正常接收输入的数据并且提交 但是后端接收到的数据为空,后端接口也没有问题 但后端收…...
css3的过度效果transition支持哪些属性,Transition 所支持的css属性
transition-property是用来指定当元素其中一个属性改变时执行transition效果: 所支持的属性类型如下: 名称描述属性color: 通过红、绿、蓝和透明度组件变换(每个数值处理) 如: background-color, border-color, color, outline-co…...
JAVAEE初阶 文件IO(一)
这里写目录标题 一. 计算机中存储数据的设备1.1 CPU1.2 内存1.3 硬盘1.4 三种存储的区别 二.文件系统2.1 相对路径2.2 绝对路径2.3 .和..的含义2.4 例子2.5 everything工具 三.文件3.1 文本文件3.2 二进制文件 四. JAVA对于文件的API4.1 getParent getName getPath getAbsolute…...
使用WAF防御网络上的隐蔽威胁之CSRF攻击
在网络安全领域,除了常见的XSS(跨站脚本)攻击外,CSRF(跨站请求伪造)攻击也是一种常见且危险的威胁。这种攻击利用用户已经验证的身份在没有用户知情的情况下,执行非授权的操作。了解CSRF攻击的机…...
如何从 Keras 中的深度学习目录加载大型数据集
一、说明 数据集读取,使用、在磁盘上存储和构建图像数据集有一些约定,以便在训练和评估深度学习模型时能够快速高效地加载。本文介绍Keras 深度学习库中的ImageDataGenerator类等工具自动加载训练、测试和验证数据集。 二、ImageDataGenerator加载数据集…...
【大数据】Flink 详解(八):SQL 篇 Ⅰ
《Flink 详解》系列(已完结),共包含以下 10 10 10 篇文章: 【大数据】Flink 详解(一):基础篇【大数据】Flink 详解(二):核心篇 Ⅰ【大数据】Flink 详解&…...
如何从命令行运行testng.xml?
目录 创建一个新的java项目并从命令行运行testng.xml 使用命令行运行XML文件 从命令行运行现有maven项目的XML文件 在这篇文章中,我们将使用命令行运行testng.xml。有多种场景需要使用命令行工具运行testng.xml。也许您已经创建了一个maven项目,现在想…...
MongoDB-数据库文档操作(2)
任务描述 文档数据在 MongoDB 中的查询和删除。 相关知识 本文将教你掌握: 查询文档命令;删除文档命令。 查询文档 我们先插入文档到集合 stu1 : document([{ name:张小华, sex:男, age:20, phone:12356986594, hobbies:[打篮球,踢足球…...
文件包含介绍
本地文件包含 常见的文件包含漏洞的形式为 <?php include("inc/" . $_GET[file]); ?> 考虑常用的几种包含方式为 同目录包含file.htaccess目录遍历?file…/…/…/…/…/…/…/…/…/var/lib/locate.db日志注入?file…/…/…/…/…/…/…/…/…/var/log/a…...
C语言——小细节和小知识9
一、大小端字节序 1、介绍 在计算机系统中,大小端(Endianness)是指多字节数据的存储和读取顺序。它是数据在内存中如何排列的问题,特别是与字节顺序相关。C语言中的数据存储大小端字节序指的是在内存中存储的多字节数据类型&…...
uni-app基础详解(组件、弹窗、数据缓存、页面跳转)
uni-app基础详解(组件、弹窗、数据缓存、页面跳转) uni-app组件scroll-viewswipertext 文本button 按钮input 输入框radio 单选checkbox 多选picker 选择器slider 滑块textarea 文本域 弹窗提示框 uni.showLoading提示弹窗 uni.showToast确定取消框 uni.…...
LabVIEW模拟荧光显微管滑动实验
LabVIEW模拟荧光显微管滑动实验 在现代生物医学研究中,对微观生物过程的精准模拟和观察至关重要。本案例展示了如何利用LabVIEW软件和专业硬件平台,创新地模拟荧光显微管在滑动实验中的动态行为,这一过程不仅提升了实验效率,还为…...
Springboot项目:解决@Async注解获取不到上下文信息问题
问题描述 springboot项目中,需要使用到异步调用某个方法,此时 第一个想到的就是 Async 注解,但是 发现 方法执行报错了,具体报错如下: java.lang.NullPointerExceptionat com.ruoyi.common.utils.ServletUtils.getRe…...
国内镜像:极速下载编译WebRTC源码(For Android/Linux/IOS)(二十四)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…...
ThinkPHP为什么用PHP+Swoole协程模式部署运行
看很多ThinkPHP框架的程序商城等系统,现在都用PHPSwoole协程来运行。在说Swoole前我们先了解下传统PHP模式。 PHP-FPM 的对象常驻内存问题 互联网发展早期,大部分项目的业务逻辑并没有那么复杂,技术生态相对比较简单,也没有 Com…...
【芯片测试】:SmarTest 开发环境入门
SmarTest 开发环境入门:Eclipse IDE 集成与工作区管理系列: Advantest V93000 SmarTest 8 核心概念解析|第 1 篇(共 8 篇) 适合读者: 初次接触 SmarTest 的测试工程师、ATE 软件开发者前言 很多工程师第一次…...
okbiye 降重 | 降 AIGC 功能实测:双标检测时代,论文合规通关的新解法
okbiye-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/AI PPT降重复率 - Okbiye智能写作https://www.okbiye.com/reduceAIGC 引言:从 “单查重” 到 “双标审”,毕业论文合规压力的全面升级 当你熬夜写完一篇万字毕业论文,用查…...
深入LTPI状态机:为什么你的链路配置总失败?Advertise与Configure状态详解
深入LTPI状态机:为什么你的链路配置总失败?Advertise与Configure状态详解 在LTPI协议的实际部署中,许多工程师都会遇到一个令人困惑的现象:明明按照规范完成了链路训练,却在配置阶段频繁出现回退到Link Detect状态的情…...
ChatGPT生成的SQL注入漏洞代码竟通过了87%静态扫描器?安全团队紧急避坑指南(含检测脚本)
更多请点击: https://codechina.net 第一章:ChatGPT生成的SQL注入漏洞代码竟通过了87%静态扫描器?安全团队紧急避坑指南(含检测脚本) 近期,某金融企业安全团队在代码审计中发现,一段由ChatGPT生…...
通用人工智能(AGI)完整技术方案:以字序生命模型(WOLM)为认知内核的双脑协同架构
一、AGI的终极定义在讨论技术方案之前,先定义什么是AGI。当前主流的AGI定义,强调一个系统能在绝大多数人类能做的智力任务上达到或超越人类水平。这个定义隐含了一个假设:AGI的核心是“智力”——逻辑推理、知识储备、创造力。我们的定义不同…...
京东评论拿到数据后对比同款竞品评论,看别家优势短板,找自身差异化卖点
京东评论已修复,需要的可以联系我留言一、数据归集抓取自家、2-3 款核心竞品近 3-6 个月评论,拆分好评、中差评统一维度:产品功能、做工品质、价格、物流售后、外观体验、适配性二、拆解优劣维度竞品优势统计高频夸赞词,汇总核心加…...
模拟几种数据融合协作频谱感知技术在认知无线电应用中性能研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
WireUI颜色选择器和日期选择器:提升用户体验的利器 [特殊字符][特殊字符]
WireUI颜色选择器和日期选择器:提升用户体验的利器 🎨📅 【免费下载链接】wireui TallStack UI components 项目地址: https://gitcode.com/gh_mirrors/wi/wireui WireUI颜色选择器和日期选择器是Laravel Livewire应用中提升用户体验的…...
为AI智能体项目选择与接入高性价比大模型API服务
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为AI智能体项目选择与接入高性价比大模型API服务 在构建AI智能体或自动化工作流时,开发者面临的核心挑战往往集中在两个…...
如何快速搭建个人游戏串流服务器:Sunshine跨平台游戏流媒体完整指南
如何快速搭建个人游戏串流服务器:Sunshine跨平台游戏流媒体完整指南 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 想要在任何设备上畅玩PC游戏?Sunshine游…...
