HTTP(超文本传输协议)是一种用于分布式、协作和超媒体信息系统的应用层协议。 HTTP 是万维网数据通信的基础。
请求方法
方法的含义
请求一些选项信息,让客户端查看服务器的性能
得到
请求指定页面信息并返回实体主体
头
类似于get请求,只是返回的中没有具体内容,用于获取
邮政
向指定资源提交数据以处理请求(例如提交表单或上传文件)。 数据包含在请求正文中。 POST 请求可能会导致创建新资源和/或修改现有资源
放
客户端发送给服务器的数据替换指定文档的内容
请求服务器删除指定页面
痕迹
echo 服务器收到的请求,主要用于测试或诊断
状态码(-Code)
2xx:表示成功,比如收到或者知道
3xx:表示重定向,必须采取进一步的行动才能完成请求
4xx:表示客户端错误,例如语法不正确或无法完成请求
5xx:表示服务器错误,如服务器故障无法完成请求
更多状态码:菜鸟教程。 HTTP 状态代码
其他协议
SNMP(简单网络管理协议)是互联网工程任务组(IETF,Task Force)定义的协议族的一部分。 该协议支持网络管理系统监控连接到网络的设备是否存在任何管理问题。
网络编程中的read()、write()函数
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
TCP的三次握手在read()write()中建立连接
我们知道TCP建立连接需要进行“三次握手”,即交换三个数据包。 大致流程如下:
客户端向服务器发送一个 SYN J
服务器用 SYN K 响应客户端并用 ACK J+1 确认 SYN J
客户端希望服务器发送确认ACK K+1
只是三次握手就结束了,但是这个三次握手是在哪些函数中发生的呢? 请看下图:
发送的TCP三次握手
从图中可以看出:
客户端调用时,触发连接请求,向服务端发送SYN J包,进入阻塞状态;
服务端监听连接请求,即收到SYN J包,调用接收请求的函数向客户端发送SYN K、ACK J+1,此时进入阻塞状态;
客户端收到服务器的SYN K和ACK J+1后,此时返回并确认SYN K;
服务器收到ACK K+1后返回,三次握手完成,连接建立。
TCP中的四次握手释放连接
上面介绍了TCP的三次握手建立过程和涉及的函数。 下面介绍一下四次握手释放连接过程,请看下图:
发送的TCP四次握手
图解过程如下:
一个应用进程首先调用close主动关闭连接,然后TCP发送一个FIN M;
另一端收到FIN M后,进行被动关闭,确认FIN。 它的接收也作为文件结束传递给应用进程,因为FIN的接收意味着应用进程不能再在相应的连接上接收额外的数据;
一段时间后,接收到文件末尾的应用程序调用 close 将其关闭。 这导致它的 TCP 也发送一个 FIN N;
收到此 FIN 的源发送方 TCP 确认它。
这样每个方向都有一个FIN和ACK。
数据库范式设计模式
主要设计模式示例参考:CSDN专栏。 C++设计模式系列博文
设计模式项目目录
单例模式
单例模式示例
抽象工厂模式
抽象工厂模式的例子
适配器模式
适配器模式示例
桥接模式
桥接模式示例
观察者模式
观察者模式示例
设计模式六大原则链接加载库内存、栈、堆
一般的应用内存空间有以下几个区域:
堆栈
栈保存了一次函数调用所需的维护信息,常称为栈帧(Stack frame)或活动记录( ),一般包括以下几个方面:
堆
堆分配算法:
“ fault(故障)”或“非法操作,无法读取/写入此内存地址”
非法指针解除引用引起的典型错误。 当指针指向一个不允许读写的内存地址,但程序试图使用指针对该地址进行读写时,就会出现该错误。
常见原因:
编译链接各平台文件格式
平台可执行文件目标文件动态库/共享对象静态库
EXE文件
对象
动态链接库
库
Unix/Linux系统
精灵,出局
o
所以
A
苹果
马赫-O
o
dylib,待定,
A。
编译链接过程
预编译(预编译器处理#、#等预编译指令,生成.i或.ii文件)
编译(编译器进行词法分析、句法分析、语义分析、中间代码生成、目标代码生成、优化,生成.s文件)
汇编(汇编器将汇编代码翻译成机器码并生成.o文件)
链接(链接器进行地址和空间分配、符号解析、重定位、生成 .out 文件)
当前版本的GCC将预编译和编译合二为一,预编译器 cc1, as, ld
MSVC编译环境、编译器cl、链接器链接、可执行文件查看器
目标文件
编译器编译源代码后生成的文件称为目标文件。 从结构上来说,目标文件是一种编译后的可执行文件格式,只是还没有链接,可能有些符号或者地址还没有调整。
可执行文件(.exe for Linux and ELF for Linux)、动态链接库(.dll for Linux and .so for Linux)、静态链接库(.lib for Linux and .a for Linux)均以可执行文件格式存储(根据 PE-COFF,Linux 根据 ELF)
目标文件格式
PE和ELF都是COFF的变种(文件)
对象文件存储结构
段函数
文件
文件头,描述了整个文件的文件属性(包括文件是否可执行,是静态链接还是动态链接及入口地址,目标硬件,目标操作系统等)
。文本
代码段,编译成执行语句的机器码
。数据
.bss
BSS段(Block by),未初始化的全局变量和局部静态变量(因为默认值为0,所以这里只是保留,不占用空间)
.
只读数据段,存放只读数据,一般是程序中的只读变量(比如用const修饰的变量)和字符串常量
.
注解信息段,存放编译器版本信息
.note.GNU 堆栈
堆栈提示
其他款
链接界面 - 符号
在链接中,目标文件实际上是目标文件之间地址的引用,即函数和变量地址的引用。 我们把函数和变量统称为符号(),函数名或变量名就是符号名(Name)。
下面是符号表(Table):
(符号名称)值(地址)
主要的
0x100
添加
0x123
...
...
Linux 的共享库 ( )
Linux下的共享库就是一个普通的ELF共享对象。
共享库版本更新应确保二进制接口 ABI() 兼容性
姓名
.so.xyz
小路
大多数开源系统,包括 Linux,都遵循 FHS(文件)标准,该标准指定了系统文件的存储方式,包括每个目录的结构、组织和作用。
动态链接器在/lib、/usr/lib和/etc/ld.so.conf配置文件指定的目录中查找共享库
环境变量so 是使用CLion编写共享库
创建一个名为的共享库
。TXT
cmake_minimum_required(VERSION 3.10)
project(MySharedLib)
set(CMAKE_CXX_STANDARD 11)
add_library(MySharedLib SHARED library.cpp library.h)
。H
#ifndef MYSHAREDLIB_LIBRARY_H
#define MYSHAREDLIB_LIBRARY_H
// 打印 Hello World!
void hello();
// 使用可变模版参数求和
template <typename T>
T sum(T t)
{
return t;
}
template <typename T, typename ...Types>
T sum(T first, Types ... rest)
{
return first + sum(rest...);
}
#endif
.cpp
#include
#include "library.h"
void hello() {
std::cout << "Hello, World!" << std::endl;
}
so共享库的使用(可执行项目调用)使用CLion调用共享库
创建一个名为的可执行项目
。TXT
cmake_minimum_required(VERSION 3.10)
project(TestSharedLib)
# C++11 编译
set(CMAKE_CXX_STANDARD 11)
# 头文件路径
set(INC_DIR /home/xx/code/clion/MySharedLib)
# 库文件路径
set(LIB_DIR /home/xx/code/clion/MySharedLib/cmake-build-debug)
include_directories(${INC_DIR})
link_directories(${LIB_DIR})
link_libraries(MySharedLib)
add_executable(TestSharedLib main.cpp)
# 链接 MySharedLib 库
target_link_libraries(TestSharedLib MySharedLib)
主.cpp
#include
#include "library.h"
using std::cout;
using std::endl;
int main() {
hello();
cout << "1 + 2 = " << sum(1,2) << endl;
cout << "1 + 2 + 3 = " << sum(1,2,3) << endl;
return 0;
}
的结果
Hello, World!
1 + 2 = 3
1 + 2 + 3 = 6
应用入口函数和函数声明
Int WINAPI _tWinMain(
HINSTANCE hInstanceExe,
HINSTANCE,
PTSTR pszCmdLine,
int nCmdShow);
int _tmain(
int argc,
TCHAR *argv[],
TCHAR *envp[]);
应用程序类型入口点函数嵌入式可执行文件的启动函数
处理 ANSI 字符(字符串)的 GUI 应用程序
()
处理字符(字符串)的 GUI 应用程序
()
处理 ANSI 字符(字符串)的 CUI 应用程序
(主要的)
处理字符(字符串)的 CUI 应用程序
(wMain)
动态链接库(-link)
动态链接库(-link)
知识点来自《核心程序设计(第五版)》
注意的搜索顺序很有用
包含可执行文件的目录
系统目录可以通过
16位系统目录,即目录中的子目录
目录,可以通过
进程的当前目录
PATH 环境变量中列出的目录
DLL入口函数函数
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
// 第一次将一个DLL映射到进程地址空间时调用
// The DLL is being mapped into the process' address space.
break;
case DLL_THREAD_ATTACH:
// 当进程创建一个线程的时候,用于告诉DLL执行与线程相关的初始化(非主线程执行)
// A thread is bing created.
break;
case DLL_THREAD_DETACH:
// 系统调用 ExitThread 线程退出前,即将终止的线程通过告诉DLL执行与线程相关的清理
// A thread is exiting cleanly.
break;
case DLL_PROCESS_DETACH:
// 将一个DLL从进程的地址空间时调用
// The DLL is being unmapped from the process' address space.
break;
}
return (TRUE); // Used only for DLL_PROCESS_ATTACH
}
加载和卸载库读取函数声明
// 载入库
HMODULE WINAPI LoadLibrary(
_In_ LPCTSTR lpFileName
);
HMODULE LoadLibraryExA(
LPCSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags
);
// 若要在通用 Windows 平台(UWP)应用中加载 Win32 DLL,需要调用 LoadPackagedLibrary,而不是 LoadLibrary 或 LoadLibraryEx
HMODULE LoadPackagedLibrary(
LPCWSTR lpwLibFileName,
DWORD Reserved
);
// 卸载库
BOOL WINAPI FreeLibrary(
_In_ HMODULE hModule
);
// 卸载库和退出线程
VOID WINAPI FreeLibraryAndExitThread(
_In_ HMODULE hModule,
_In_ DWORD dwExitCode
);
显式链接到导出的符号函数声明
FARPROC GetProcAddress(
HMODULE hInstDll,
PCSTR pszSymbolName // 只能接受 ANSI 字符串,不能是 Unicode
);
.exe查看DLL信息
在VS的开发者命令提示符下使用.exe查看DLL库的导出段(导出的变量、函数、类名的符号)、相对虚拟地址(RVA、.)。 喜欢:
DUMPBIN -exports D:\mydll.dll
DLL头文件
// MyLib.h
#ifdef MYLIBAPI
// MYLIBAPI 应该在全部 DLL 源文件的 include "Mylib.h" 之前被定义
// 全部函数/变量正在被导出
#else
// 这个头文件被一个exe源代码模块包含,意味着全部函数/变量被导入
#define MYLIBAPI extern "C" __declspec(dllimport)
#endif
// 这里定义任何的数据结构和符号
// 定义导出的变量(避免导出变量)
MYLIBAPI int g_nResult;
// 定义导出函数原型
MYLIBAPI int Add(int nLeft, int nRight);
动态链接库源文件
// MyLibFile1.cpp
// 包含标准Windows和C运行时头文件
#include
// DLL源码文件导出的函数和变量
#define MYLIBAPI extern "C" __declspec(dllexport)
// 包含导出的数据结构、符号、函数、变量
#include "MyLib.h"
// 将此DLL源代码文件的代码放在此处
int g_nResult;
int Add(int nLeft, int nRight)
{
g_nResult = nLeft + nRight;
return g_nResult;
}
DLL库的使用(运行时动态链接DLL) DLL库的使用(运行时动态链接DLL)
// A simple program that uses LoadLibrary and
// GetProcAddress to access myPuts from Myputs.dll.
#include
#include
typedef int (__cdecl *MYPROC)(LPWSTR);
int main( void )
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimelinkSuccess = FALSE;
// Get a handle to the DLL module.
hinstLib = LoadLibrary(TEXT("MyPuts.dll"));
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "myPuts");
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimelinkSuccess = TRUE;
(ProcAdd) (L"Message sent to the DLL function\n");
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimelinkSuccess)
printf("Message printed from executable\n");
return 0;
}
运行时库( ) 典型程序运行步骤
操作系统创建一个进程并把控制权交给程序的入口(通常是运行时库中的一个入口函数)
入口函数初始化运行时库和程序运行时环境(包括堆、I/O、线程、全局变量构造等)。
入口函数初始化完成后,调用main函数,正式开始执行程序的主体部分。
main函数执行完毕后,返回入口函数进行清理(包括全局变量销毁、堆销毁、关闭I/O等),然后进行系统调用结束进程。
程序的I/O是指程序与外界的交互,包括文件、监视器、网络、命令行、信号等。更广泛地说,I/O是指操作系统理解的“文件” ”。
glibc 条目
-> -> 退出 -> _exit
其中执行了 main(argc, argv, ) 函数。
MSVC CRT 条目
整数(无效)
请执行下列操作:
初始化与操作系统版本相关的全局变量。
初始化堆。
初始化 I/O。
获取命令行参数和环境变量。
为 C 库初始化一些数据。
调用 main 并记录返回值。
检查错误并返回main的返回值。
C 语言运行时 (CRT)
大致包括以下功能:
C语言标准库(ANSI C)
包括:
海量数据处理 音视频 其他书籍 语言 算法 系统 网络 其他
本公众号全部博文已整理成一个目录,请在公众号里回复「m」获取! 推荐阅读:
5T技术资源大放送!包括但不限于:C/C++,Linux,Python,Java,PHP,人工智能,单片机,树莓派,等等。在公众号内回复「1024」,即可免费获取!!