C/C++ myls_goto
2024-03-30 18:56:03 0 举报
AI智能生成
C/C++ myls_goto
作者其他创作
大纲/内容
http://81.68.177.28/index.html
1933887389@qq.com
个人网站/邮箱
CF
原神
DNF
我的世界
客户端
C
lua
Skynet(网易游戏用的服务器框架)
服务器
游戏
libevent
nignx
TinyHttp
其他
QQ
微信
其他聊天软件
im
冰箱
洗衣机
热水器
汽车
等其他
嵌入式
快手
抖音
哔哩哔哩
YY
等其他直播平台
直播
ARM
英特尔
芯片
股票
量化交易
汽车公司
自动驾驶
大厂
人工智能
神经网络
机器学习
C/C++ 擅长领域涉及
C++语法
数据结构与算法
TCP/IP 网络
系统底层
项目经验
内容
第一章 介绍
C/C++语法糖 封装继承多态 重载
C++对象模型
C/C++语法
语言是给机器执行
查看汇编代码
编译器工作原理
开始
如果new 数组的话,是申请了数组自身空间+整数(数组大小)
一片连续的空间
数组访问越界通常不会导致程序崩溃,但可能会导致未定义的行为。当访问数组越界时,程序可能会访问到不属于该数组的内存地址,从而导致未定义的行为。这可能会导致程序崩溃,也可能会导致其他错误。
访问不会,但写就会出现未知情况
数组访问越界会crash吗? 访问a[5]会如何?
只传递了地址 int a[]是个语法糖 int *a
参数传递
数组的定义
数组定义和作为函数参数的区别
.dll 或 .so的实现者呢,在类中定义添加了成员变量,更改了成员函数的实现,但是函数参数没有改变于是只给调用者更新了.dll和.so文件
使用者拿到.h头文件和.dll或者.so可执行文件
头文件中类的定义
类对象大小看谁?
函数
类导出的是什么?
结果会产生一个未知的错误
一个DLL或是一个SO导出了一个类
DLL导类,调用者未变化,实现者增加了成员会如何
是否带this指针
普通的函数就是全局的作用域 限制在本文件使用
类中的static是看作用域是public才能对外可见 还可以访问自己类中的其他成员static成员函数
this rcx指针传递到函数内
参数不同
类中的static函数需要带上作用域:: 或者 -> 或者 .
调用方式不同
普通函数与类中的static函数的区别?
类内static函数和一般成员函数有何区别
传递常量时候会产生临时变量或对象
函数参数为const引用
const何时产生临时对象?
修饰返回值
用于函数返回值前
可以编译通过
加与不加是两个函数,临时对象
函数参数列表中
const Class * const this
函数参数列表后
const 修饰成员函数成员?
可以用表达式计算常量,必须在编译时候确定具体的值
constexpr是C++11后的新特性
可以在运行时候指向变量
const
const 和 constexpr的区别
详细地谈const
仅仅是申请了一块内存 返回值是void*
C语言中stdlib中的函数
malloc
调用operator new 函数 底层还是调用malloc函数
先申请一块内容
再给 对象 初始化
调用构造函数
C++中的操作符
new
malloc和new的区别
是函数,用于分配内存的
operator new
操作符,先调用opertaor new函数分配内存 ,再调用构造函数来进行对象的初始化
new operator
operatorNew 和 newOperator 的区别
new[]出的内存大小 1024+8(64位) new出来的是在堆上面的内存底层是一个双向链表串起来的 delete的时候要把这个双向链表里的这个节点移除下去和去其他没有被释放的内存连成一串
operator delete / delete[] 底层调用operator delete 函数 或者 operator delete[]的函数
两点补充
结果是未定义或者会发生crash
用operator new[]申请的空间用delete释放结果是未定义的有可能产生程序内存泄露或者程序发生crash (取决于不同的编译器)
总结
new[]出来的指针使用delete会如何?
delete 和 detele[]的区别
告诉编译器用C语言的命名方式和调用约定
C语言无法实现函数的重载
目的
引用外部用C语言写来编译函数名不可以更改或重载
extern \"C\" 的作用
比如在FFmpeg中就要使用 因为FFmpeg是用C语言写的
extern \"C\" 的含义
函数名相同
2个特性
本质上还是两个函数名
编译器根据参数把函数名称进行了重新命名
编译器
C++如何实现函数重载的?
函数名只有一种命名规则
不可以
C语言可以实现函数的重载吗?
函数重载
什么是函数重载
struct默认的访问权限是public(成员,继承)
使用习惯不同,只定义数据用struct
class还可以用于模板定义,struct不可以用于模板定义
正确的回答
struct 和 class的区别
游戏开发
IM开发 比如QQ 微信 基于TCP协议
C/S二进制协议开发
C/S对齐方式不同带来的问题
对齐方式
应用场景
约定对齐的方式
一种解决方案
以成员中出现的最大基础数据类型为分配粒度
小数据能凑则凑
成员空间分配原则
默认对齐规则
typedef struct S{ //空结构体大小是1个字节}SS;
typedef struct S{ //4+1+2 8 int i; char c; short s;}SS;
typedef struct S{ //1+2+4+2 12 char c; short s; int i; short sh;}SS;
typedef struct S{ //1+8+2+4 24 char c; long long l; short s; int i;}SS;
例子
结构体成员的对齐问题
不要直接放进CPU寄存器优化,每次要从内存中存取
说给编译器听的 给编译器传达不要优化的信息
volatile 中文 易变的
volatile变量
参数必然是确定的不可变
参数是被调用者退栈
stdcall
支持参数可变
参数是调用者退栈,调用者知道传递了多少参数
cdecl
在RET指令RETRUN缩写RETURN指令里面就是返回他是把返回值放在栈里面然后在RETURNT退出的时候退出栈的时候从栈里面拿到函数的下一行代码也就是下一句指令这也就是函数调用它怎么返回来的
调用完一个函数它是怎么找到下一个执行代码的?
windows api函数的参数是否可变?
stdcall函数的参数是否可变
构造函数体
初始化列表
成员定义时候 (C++新特性 本质上和初始化列表是一样的)
三种初始化方式
基类
初始化列表(定义时候赋初值) 同时存在是互斥的初始化列表取代掉定义时候赋初值
构造函数 函数体内进行初始化
初始化顺序
构造函数的初始化顺序
变量的地址,只访问地址中的内容(只能对地址里面的内容进行++ --)
引用
变量的地址,不但可以访问地址中的内容,而且自身也可以运算(地址可以 ++ --)
指针
编译器眼里的
初始化时候必须指向一个对象,永远只操作对象本身(*p)
分配内存,可赋空值,可进行运算
人可以这么理解
指针和引用的区别
base::fun1
base::fun2
父类虚函数表(存放的地址 地址指向具体的函数)
derived::fun1
derived::fun2
(父类的指针new子类对象的时候此时虚表指针会指向子类的虚函数表)子类虚函数表(子类的虚函数表的地址是指向子类的函数地址)
虚表指针
虚函数
C++是如何实现多态
属于对象的
虚表指针是属于谁?
构造函数里初始化(编译器安插的代码)
虚表指针何时初始化的?
虚函数表指针它是属于对象的并且往往大部分编译器是放在第一个元素也就是说对象的第一个元素然后在构造函数的时候对它进行初始化
总结
虚表指针是何时赋值的
静态存储区内
数据的只读存储区
代码段
编译器就可以确定的,(属于类的)对象共享的
虚函数表存放在什么位置
把const指针赋值给普通类型
去除只读属性
const_cast
向上向下都可以转,只做移位操作
只做类型检查(子类到父类或者父类到子类会检查有没有继承关系),不做安全检查
static_cast(往往用在父类和子类之间的转换)(只做值的位移检查)
向下转型,失败返回空(因为有运行时的运行检查)
做类型和RTTI(运行时的)检查 是否是继承关系上不是返回一个NULL的处理
dynamic_cast(正是因为dynamic_cast有类型检查所以它的速度运行速度肯定是比static_cast慢一些的因为它有一个函数调用有一个类型的检查)
直接转换,靠程序员自己自行判断,比较危险!
不做类型检查
reinterpret_cast (只是帮忙做类型切换,类型匹不匹配它不管,它只是保证C++语法 能编译过去,但是值它是不变的,靠程序员自行来判断)
cast 系列 指针转换区别 xxx_cast<new_type>(expression)
它的构造还是delete 类型 也就是说它是不可以访问的禁止访问的,构造不可以访问还有赋值也不可以访问,所以只能当作右值在使用
type_info
从上往下转换,从父类转子类的时候才用到了RTTI的信息,如果说不是一个继承链上它会返回一个空指针
可以是安全的类型转换
dynamic_cast
运行时的运行信息(什么是运行时比如说虚函数多态用一个父类的指针区New了一个子类编译的时候它是没有办法确定this指针的到底是指向基类还是指向子类它是没有办法确认的就在运行的时候才能决定所以这就叫做运行时)
Run-Time Type Information
什么是RTTI
可以取typeinfo这个对象,这个对象是不可访问的仿函数,只能访问里面的成员函数,比如说常用的name(到底是什么类),还有一个是判断是否相等
typeid往往做类型判断的使用,C++里面是没有反射的,而java go 都有反射,如何获取类型信息typeid就是很重要,可以判断类型,可以提取出来它是什么类型的
可以用来做类型判断
typeid
如何获取RTTI
RTTI信息本身也是一个只读的,类似于虚表一样也是只读的,虚表它可以存在只读存储区也可以放在代码段看不同的编译器不同的实现,RTTI的指针往往存在在虚表的附近有的编译器是放在虚表的上面上一个位置当然不同的编译器有不同的实现。
存储在虚函数表的附近
RTTI存储在哪里
(注意)指针指向的那块空间对象是一样的,但是指针类型是不一样的
rtti
static_cast运算
子类是否会合并虚函数表?
一个子类,同时继承了都带有虚函数的父类,问:子类最小多大?(第一种答案:子类有8个字节把虚函数合并成一个虚函数表。第二种答案:两个8字节分别指向两个父类的虚表。 也就是说子类的虚表可以是一个核心的起点在于合并还是不合并的问题。)
继承两个虚函数类它的子类至少也是16个字节分别两存放不同的虚函数表
两个父类都有虚函数,子类至少有多大
析构函数加virtual的话意为这它的子类也是虚函数,这形成了多态。如果不加父类里面就没有虚函数那就是没有虚表所以会直接调用析构函数所以就不会实现多态,所以直接到了父类的析构函数它并没有调用到子类的析构函数并且还存在问题因为obj父类的所以这里不但没有实现多态还可能产生一些不可预期的错误
是否是虚函数
我们在delete父类的时候它会调用继承类的析构函数
子类析构函数是否具备多态特性
析构函数加不加virtual有何区别
thread_local int x=0; //调试时候断点失效,语句不会被执行,在编译的时候就已经确定了,不会像栈上的数据一样是在运行期间的时候才会给它分配空间并且赋初始值所以那种断点是可以断到的而这种断不到是类似于static它是存储在某个区域里面然后并且是在执行前就已经给它分配好了这块空间所以我们在动态执行的时候这句话是没办法打断点的。static修饰的局部变量它是在作用域是在函数内但是它的生命周期是在外面是静态存储区整个程序的进程空间,那thread_local的生命周期随着线程的存在而存在线程的消亡而消亡线程没有消亡它就是一直存在的
thread_local 变量生命周期如何?
如何定义线程的私有数据
gs:global segment 全局数据段 (都共享的)
所以两次调用x的地址是不一样的
不同的线程都有自己的寄存器和寄存器的值,所以不同的线程看到的拿到的gs里面的数据是不一样的
tls:qword ptr gs:[58h] thread local storage 线程局部存储
thread_local变量不同线程地址为何不同?
C++11的新特性
如何创建线程私有数据
[] 捕获区 支持 值+引用
() 函数参数
{}函数体
[](){}
class A{public: operator(params){}private: []捕获的作为成员};
可以理解为绑定对象的函数
lambda表达式 (类似于其他语言中的闭包)
&&
右值(无法取地址)的引用 (对程序员而言)
左值引用默认的引用编译器语义而言也是指针只不过它在使用的时候对指针的内容进行取,而右值引用对编译器来说一样也是指针,无差别的
指针(对编译器而言)
什么是右值引用?(对右值的引用)
效率(复用将亡值)使用了一次复制
为什么要有右值引用?
可以,但是使用习惯不同
左值引用不可实现吗?
右值引用是为了提升效率去复用一个将亡值里面内存
右值
左值引用是往往用法不一样它如果说要复用将亡值也是可以的但是使用习惯不一样因此推出了一个右值引用概念
左值
右值引用
使用完之后极有可能不在使用了 这就是移动语义
把左值赋给右值 std::move
在opeartor= 中 偷梁换柱
如何复用一个将亡左值,提升效率?
移动语义
(本身是可以取地址的)右值引用本身是一个左值
右值引用变量是左值还是右值?
可以保持右值引用还是右值引用属性
可以保持左值引用还是左值引用属性
完美转发
std::forward
如何保证函数使用过程中右值属性不变?
底层左值引用和右值引用对编译来说它都是一个指针所以左值引用通过语义std::move可以把它转换成右值引用,右值引用在传递的过程中默认的它会变成左值我们要一直保持右值引用的属性不变那就借助std::forward也就是所谓的完美转发
为什么左值引用和右值引用可以转化呢?
首先右值引用它和左值引用一样对编译器来说都是取的指针
传递的过程中右值引用的属性会丢失索引,我们要用std::forward取保持它的属性 std::forward就是完美转发
右值引用与移动语义与完美转发
override 表面重写了某个虚函数,避免写错时候新建了一个虚函数
覆盖父类的虚函数
编译器来规避虚函数编码错误
override
则不允许派生类进行覆盖/重写
不可以继承子类不可以在实现它
final
override 和 final 的作用(都是用在virtual )
自己享有管理这个对象的生命周期
独享变量
独一的独占的
被赋值后置成NULL
为什么不要auto_ptr
unique_ptr
共享指针
共享引用计数
底层用了
共享变量
shared_ptr
为了解决shared_ptr的循环引用而来
class Ashared_ptr<B>
class Bshared_ptr<B>
例子:
共享shared_ptr引用计数
使用lock接口来获取对象指针
共享引用计数对象
weak_ptr
三个ptr智能指针的区别
赋值+1
销毁-1
减0 释放对象
引用计数
引用计数也必须在堆上
栈上
shared_ptr 对象分配在哪里
构造函数
初始化的时候
operator=函数
赋值
传递值的时机
管理生命周期的方式
代码实现
shared_ptr(不支持多线程)
皇上
导演
作家
等等 ... ...
生活中的单例
#include <iostream>using namespace std;//传统的方式 private 是不可用了 A a; new A;//static func 保证了唯一性class Singleton{public: static Singleton *getInstance() { if(_ins==nullptr) { _ins=new Singleton; } return _ins; }private: static Singleton *_ins;private: //构造器 和 析构器 私有化 //意为这常规的构造器 和 析构器 不可以使用 Singleton(){} ~Singleton(){} Singleton(const Singleton&s){} Singleton&operator=(const Singleton&s){}};Singleton *Singleton::_ins=nullptr;int main(){ Singleton*ps=Singleton::getInstance(); return 0;}
代码
#include <iostream>#include \"a.h\"#include \"b.h\"#include \"c.h\"using namespace std;//A B C 均要用到配置文件 xx.conf 不使用全局变量 -------》 单例//单例 是 共享数据,取代全局变量,行之有效的方案int main(){ A a; B b; C c; return 0;}
main.cpp
config.h
#include \"config.h\"#include <fstream>#include <iostream>Config*Config::_ins=nullptr;Config *Config::getIns(){ if(_ins==nullptr) { _ins=new Config; } return _ins;}Config::Config(){ fstream fs; fs.open(\"ip_and_port.conf\
config.cpp
#ifndef A_H#define A_H#include \"config.h\"class A{public: A();};#endif // A_H
a.h
#include \"a.h\"A::A(){ Config*Conf=Config::getIns(); cout<<\"ip:\"<<Conf->getIp()<<endl; cout<<\"Port:\"<<Conf->getPort()<<endl;}
a.cpp
#ifndef B_H#define B_H#include \"config.h\"class B{public: B();};#endif // B_H
b.h
#include \"b.h\"B::B(){ Config*Conf=Config::getIns(); cout<<\"ip:\"<<Conf->getIp()<<endl; cout<<\"Port:\"<<Conf->getPort()<<endl;}
b.cpp
#ifndef C_H#define C_H#include \"config.h\"class C{public: C();};#endif // C_H
c.h
#include \"c.h\"C::C(){ Config*Conf=Config::getIns(); cout<<\"ip:\"<<Conf->getIp()<<endl; cout<<\"Port:\"<<Conf->getPort()<<endl;}
c.cpp
Config (A B C 均要用到配置文件 xx.conf 不使用全局变量 -------》 单例)
应用代码
单例模式(保证一个类只有一个实例)
auto dir=Director::getInstance();
以及含有二段式初始化
cocos2dx游戏引擎中导演的单例
单例 是 共享数据,取代全局变量,行之有效的方案
设计模式 Singleton 单例模式(单例基本用于运行程序中第一次使用结束到程序挂掉)
<<C++对象模型>>
汇编
理解编译器工作原理
C/C++语言完结
第二章 C/C++语法
开始
链表反转
链表合并
区间合并
图像旋转
矩阵相乘
两数之和
LRU缓存
最长无重复字符串
字符串表达式运算
非递归遍历二叉树
二叉树公共最近祖先
数组全排列
连续子数组最大和
最长公共字串
最长回文子串
数组子集
哈希表实现原理
string内部数据结构
verctor考点
数组
map考点
B+树与索引
算法结束
算法篇
子主题
单向链表
选择
冒泡
快速
插入
希尔
排序
二分查找
线性查找
查找
mystrlen
mystrcpy
mystrcat
mystrcmp
myString ---------- 函数
myString
myString ———— cpp
第三章 数据结构与算法
IP
TCP/UDP
HTTP
WebSocket
HTTP2.0/HTTP3.0
在校园或公司内访问百度时,数据在本机和服务器之间的往返需要经过以下步骤:当你输入百度网址并按下回车键时,浏览器会向百度的服务器发送一个HTTP请求。这个请求中包含了你的IP地址、请求的网页地址(URL)、浏览器类型和版本等信息。百度的服务器收到请求后,会根据请求中的URL查找对应的网页内容。找到内容后,服务器会将网页内容返回给浏览器。浏览器收到服务器返回的网页内容后,会解析HTML、CSS和JavaScript代码,然后将网页显示在你的电脑上。如果你在网页中输入了信息并提交表单,浏览器会将你的信息发送至百度的服务器。服务器收到信息后,会根据相应的服务逻辑处理你的请求,然后将处理结果返回给浏览器。浏览器收到服务器返回的结果后,会解析并显示给你。在整个过程中,数据在本机和服务器之间的往返主要是通过HTTP协议进行的。HTTP协议是一种无状态协议,即服务器不会存储客户端的请求信息。每次请求都会包含完整的请求信息,服务器处理完请求后,会将响应结果返回给客户端,然后断开连接。
在校园/公司内访问百度,数据是如何从本机到服务器之间往返?
是的,两个校园局域网内的学生可以通过P2P(点对点)方式进行视频通话。P2P是一种网络拓扑结构,允许数据直接在客户端之间传输,而不需要经过中心服务器。这种方式可以减少服务器负担,提高传输效率。对于视频通话,可以使用不同的P2P技术,如WebRTC。WebRTC是一种实现实时音视频通信的开源技术,允许在浏览器之间进行点对点的音视频和数据传输。两个学生可以通过WebRTC在各自的局域网内建立连接,然后通过NAT穿透等技术(如STUN、TURN服务器)在不同网络之间建立连接。这样,他们就可以进行视频通话了。需要注意的是,由于网络环境复杂,P2P通信可能会受到防火墙、路由器设置等因素的影响。在实际应用中,可能需要对网络环境进行适当的配置和调整。
在两个校园局域网内的两个学生,是否可以通过P2P进行视频连续?
tracert www.baidu.com
跟踪一下路由 traceroute/tracert
解答
校园电脑如何访问百度?
TCP分层协议
40字节是错误 TCP是可以脱离IP协议并不是在一起的
TCP的上层协议未必就是IP协议,因为可以支持其他网络
20字节是正确的
TCP协议的最低长度是多少
TCP协议头
TCP协议长度
不需要。TCP协议已经在传输层对数据进行了分段,形成了TCP数据包。当TCP数据包到达网络层时,IP协议会对TCP数据包进行封装,添加IP头信息。在这种情况下,如果TCP数据包的大小超过了IP协议的最大传输单元(MTU),那么IP协议会对TCP数据包进行分片。但是,通常来说,网络设备的MTU值都已经设置得足够大,因此TCP数据包通常不需要进行IP分片。如果在特殊的网络环境下,确实需要IP分片,那么IP协议会对TCP数据包进行分片。总的来说,TCP分段后通常不需要再进行IP分片,因为TCP协议已经对数据进行了合理的分段和处理。
TCP分段后还需要IP分片吗?
IP分片和TCP分段是计算机网络中两个重要的概念,它们都是用于处理数据传输过程中的大数据包的问题。IP分片是将一个大的IP数据包分成多个小的IP数据包,以便于在Internet上进行传输。当数据包的大小超过网络设备的MTU(最大传输单元)时,IP协议会将数据包分成多个小数据包,每个小数据包都包含原数据包的头部信息和一个新的数据部分。在接收端,IP协议会将这些小数据包重新组合成原来的大数据包。分片可以提高网络的传输效率,但也可能带来一些问题,如数据包丢失、重组错误等。TCP分段是将TCP数据包分成多个小的段,以便于在TCP传输过程中进行处理。TCP协议是一种可靠的传输协议,它通过序列号、确认应答、重传机制等方式来保证数据的正确传输。当TCP数据包的大小超过接收端缓冲区的尺寸或者网络带宽的限制时,TCP协议会将数据包分成多个小的段,每个小段都包含原数据包的头部信息和一部分数据。接收端会根据头部信息对这些小段进行顺序重组,以恢复原来的数据包。TCP分段可以保证数据的可靠传输,但也会增加传输延迟和数据处理的复杂性。总的来说,IP分片和TCP分段都是用于处理大数据包的问题,但它们的工作机制和目的不同。IP分片主要用于在Internet上进行大数据包的传输,而TCP分段主要用于保证数据的可靠传输和在TCP传输过程中进行处理。
谈一下IP分片和TCP分段?
TCP最大分段大小(MSS)是指TCP数据包中数据部分的最大尺寸,它的最大值通常被设定为1460字节。这个值是根据IPv4头部的最大长度(64字节)和以太网帧的最大长度(1518字节)来计算的。在TCP协议中,MSS值必须小于或等于IP分组中可用的数据空间,因为TCP头部的尺寸也必须要被考虑在内。将MSS值设定为1460字节的原因是因为这样可以在大多数网络环境下避免IP分片。分片会增加网络的复杂性,也会降低网络传输的效率,因此通常应该尽量避免。通过将MSS值设定为1460字节,可以确保TCP数据包在大多数网络环境中都可以在不进行分片的情况下进行传输。需要注意的是,MSS值并不是固定的,它可以根据网络环境进行调整。在一些高速网络环境中,更大的MSS值可能会提高网络的传输效率。然而,在其他一些网络环境中,过大的MSS值可能会导致数据包无法传输,因此需要根据具体的网络环境来选择合适的MSS值。
TCP最大分段(MSS)最大值是多少,为什么?
应用层 敲代码
传输层 TCP
网络层 ip
链路层 MAC地址
结构
TCP/IP四层结构详细图
TCP/IP四层
IP层不保证顺序,不保证可靠性(允许丢包)
增加了TCP层的重传负担,影响了性能
为什么MSS不能大于MTU-40
IP分片和TCP分段
反正法
防止被下一个相同四元组接收(对TCP效率造成了困扰)
安全考虑(被模拟攻击)
TCP报文的序列号为什么不是从0或者从1开始的
TCP 协议层 无法感知到连接被断开
电脑突然被拔掉网线
TCP 协议层 无法感知到连接被断开
电脑突然被断电了
两种情况
应用层 --》》 设计C/S心跳包
协议层 --》》 检测ACK包
如何判断TCP连接是否还在存活?
如何判断TCP连接是否还在存活
客户端发出一个SYN包 ,服务器回一个SYN包和ACK包,客户端再发一个ACK包
回答
在Syn Flood攻击中,攻击者通过伪造大量的IP地址,向目标服务器发送大量的TCP SYN请求。由于这些请求都是伪造的,服务器会响应每个请求,并等待客户端的确认。然而,由于这些请求都是伪造的,客户端并不会发送确认数据包。这导致服务器的网络连接队列被占满,从而无法处理正常的请求。
Syn Flood攻击原理是什么?
结合Sock api谈一下细节?
三次握手过程
TCP三次握手
原因:sever端socket没有被close但是服务器已经断点了
服务器close_wait是怎么形成的,如何定位问题?
TCP四次握手过程
TCP四次握手
窗口大小16位
TCP滑动窗口的作用是什么?
数据发送过程
滑动窗口的作用就是流量控制的作用它可以决定我们流量发多大或者发多小
TCP滑动窗口的作用是什么
TCP协议代码
考点
协议选择 TCP
报文长度 发送方QQ号 接收方QQ号 协议类型 聊天内容
字段考虑
如何设计QQ聊天协议?
如何设计QQ聊天协议
Socket 用于监听 =》》 bind端口 =》》 listen监听client连接(接收到客户端的connect) ==>> accept 返回新的socket通信 ==》》 recv(接受客户端数据) ==》》 send (服务器再对客户端进行响应) ==>> close 收到客户端的事件服务器也调用close ,也可以 服务器主动关闭然后通知客户端再进行关闭
Socket =>> connect (连接服务器的listen) ==》》send (发送到服务器的)==》》 recv(接受服务器的数据 ) ==》》close(服务器收到事件 服务器也调用close)
客户端1
Socket =>> connect (连接服务器的listen) ==》》send (发送到服务器的)==》》 recv(接受服务器的数据 ) ==》》close(收到服务器的close主动关闭然后客户端再关闭)
客户端2
Socket API
介绍一下TCP套接字API函数?
介绍一下TCP套接字API
TCP不会丢包 协议自身保证的 重传机制 所以不会丢包
TCP会丢包 一方数据的确发送了,另外一方真的没收到
send() ==>> 发送到Buffer缓冲区 ===》》 网络 ==》》 接收Buffer(收到了会回复一个ACK的包) 再通知用户(应用层 recv接受) (如果没有收到TCP底层有重新传送机制 重新发送给接收方 TCP不会丢包,最多发送失败) (如果一直没有发送成功会发送一个RST的标志位表示连接断开,重新建立连接,如果网络极其不好甚至RST标志位可能也收不到)==>>recv()
TCP丢包了,RST重连接后,内核不会帮忙重复数据
TCP 会发生丢包吗?
TCP并非百分之百可靠的,关键信息靠应用层保证
TCP可以保证发送的数据被对方接收到吗?
如何保证TCP一方发送的数据被另外一方接收到?
如何理解TCP的可靠传输
先收4个字节,再收6个字节
一次收10个字节
以上都有可能(收几个不保证)
客户端先 发送 4个字节,再发送6个字节,服务器是怎么接收的?
send() ==>> 发送 Buffer(类似把水加入水池) ==>>网络 ==》》 接收Buffer (数据混再Buffer里,取多少不一定)==》》recv()
对流式传输的理解?
根据协议长度来进行拆包粘包
如何拆包/粘包?
C++
写一段伪代码?
如何理解TCP的流式传输
1983 socket Unix 4.2
1994 select Linux 1.0
2002 epoll Linux 2.5.44
历史
int epoll_create(int size);//上限多少和机器有关系 size>0 即可 内核会增加
EPOLL_CTL_ADD 添加
EPOLL_CTL_MOD 修改
EPOLL_CTL_DEL 删除
int op //事件的监听
struct epoll_event{uint32_t events; epoll_data_t data;}
struct epoll_event*event
typedef union epoll_data{void *ptr;int fd;uint32_t u32;uint64_t u64;}epoll_data_t;
epoll_data_t data;
epoll
最大的socket数量 --》》 文件描述符个数 默认是1024
是否有数据,都是全量循环查询,每次都是内核调用 调用更耗时
频繁在用户态和内核态进行切换
select
前者支持高并发(文件个数),内核主动通知就绪的socket,效率更高。
epoll和select的区别?
所有socket -> 红黑树, 就绪socket-> 链表
epoll 底层使用了哪些数据结构?
前者未读写完,一直触发,后者只触发一次,效率更高。
epoll 水平模式和边缘模式的区别?
epoll和 select的区别
UDP协议是TCP协议的阉割版
可丢包,无序到达
udp协议特点,无连接,不可靠,无序
用户DIY可以自己想做啥做啥
效率高
局域网 不用考虑丢包的情况,例如腾讯的QQGame以前是前面是TCP和服务器有个连接层处理大量的客户端请求,TCP连接这台机器只做解包把包验证的协议包是合法的,随后它把这个包通过UDP转发给后面的逻辑服务器上去处理,因为它在内网之内环境比较好那udp基本上很少丢包,udp效率高
数据量大,比如RTP直播会减少延时性,视频聊天,还有以前的在公网上p2p的传输
UDP协议的应用
介绍UDP协议,以及使用场景?
UDP协议
是否使用过wireshark工具
考察是否写过HTTP程序
HTTP建立连接的过程包括以下步骤:客户端发起TCP连接请求。服务器响应TCP连接请求。客户端发送HTTP请求。服务器处理HTTP请求。服务器发送HTTP响应。客户端接收HTTP响应。关闭TCP连接。
HTTP建立连接过程
HTTP请求
HTTP响应
数据长度get受限制
安全性上,post更高
get参数在URI 链接内
get和post的区别
1.0是默认的是短链接
1.1的时候默认连接有短连接改为长连接
http1.1 和 http1.0 的主要区别是?
介绍一下HTTP协议格式
HTTP协议
了解加密算法
HTTPS是如何做到更安全的
介绍一下HTTPS建立的过程?
双方拥有相同的key
运算速度快
对称加密
两个key 一方拿着公开的key加密,另一方用私密key解密
运算速度慢
非对称加密
加密算法
因为域名劫持的问题
服务器发送公开的密钥证书给客户端
客户端去认证机构验证有效性,取公开的key
客户端使用公开的key去加密随机密码串,看服务器是否可以解密成功
引入第三方 证书中心认证机构
客户端要怎么相信服务器?
HTTP不安全
安全考虑
HTTPS协议是HTTP协议的安全版本,它在HTTP协议的基础上加入了SSL/TLS加密层,以保证数据的安全性和完整性。HTTPS建立连接的过程包括以下步骤:客户端发起TCP连接请求。服务器响应TCP连接请求。客户端发送SSL/TLS握手请求。服务器发送SSL/TLS握手响应。客户端和服务器进行SSL/TLS握手,建立加密通道。客户端发送HTTP请求。服务器处理HTTP请求。服务器发送HTTP响应。客户端接收HTTP响应。关闭TCP连接。
服务器先申请证书,然后下发证书给客户端,客户端拿到证书验证证书是否合法,客户端随机生成字符串作为对称加密的密钥给服务器,服务器用私钥解开对称密钥,服务器使用对称密钥加密数据给客户端,客户端以后的加密都会使用对称加密与服务器进行通信。在证书验证的时候用的是非对称加密,正常通信的时候用的是对称加密
HTTPS建立连接过程
HTTPS建立连接的过程
自建HTTP DNS服务
HTTP DNS 南方机房
HTTP DNS 北方机房
HTTP DNS 防单点
如何应对HTTP域名劫持的问题?
HTTP域名劫持的应对方案
HTTP2.0和HTTP1.1的主要差别
一次请求一次应答
多次请求一次应答
一次请求多次应答(服务器推送模式)
多次请求多次应答
gRPC跨语言(支持流传输)
gPRC(谷歌的)使用了HTTP2.0
HTTP2.0和HTTP1.1的主要区别
ws://host:port/path (http->ws)
请求 URL
协议升级
协议报文
服务器可以主动Web推送消息
支持二进制和文本传输(json等)
内部处理粘包的问题
WebSocket协议特点
WebSocket是可以主动通知客户端的
WebSocket协议
web ==>> Socket
WebSocket和TCP的协议不同点
WebSocket和TCP的主要区别是什么
http2.0 目前多用于服务器 和 服务器之间通信 比如说谷歌的GRPC就是用到了http2.0
TCP 并不适合在Web开发中使用
WebSocket诞生的一个原因就是解决服务器通知Web客户端原因
为什么选择WebSocket通信
为什么选择WebSocket协议
案例
WebSocket案例分析
比如:直播
无法满足低延时的需求
重传 多个RTT(Round Trip Time)
拥塞 滑动窗口的限制
弱网环境下效率非常低
QUIC 协议
HTTP3.0在QUIC协议之上
HTTP3.0
介绍一下HTTP3.0协议
结束
第四章 TCP/IP 网络
线程
进程
内存
稳定性
性能
锁和同步
线程它是内核对象
独自寄存器上下文
线程是操作系统中CPU调度的最小单元
什么是线程?
1.线程执行函数
2.线程回调函数
标准库创建void thread_func(){ std::cout<<arg1<<\" \
windows下的库函数
linux 下的库函数
栈和寄存器
比如:thread_local(线程局部存储)
TLS
(线程环境块)
TEB
线程有哪些独占资源?
函数A 调用 函数B 函数B 执行完结束后程序是如何跳转到函数调用处的 下一条语句的 ?
如何创建线程?
什么是线程它有哪些独占资源
生产消息 ==>> 消息队列 ==>> 循环消费消息
消息队列
窗口消息循环的原理?
Windows消息循环
ios消息循环
Andriod消息循环
web消息循环
线程A (std::bind 可把任何参数绑定成没有参数的func)==>> 消息队列 func_obj() ==>> 线程B
借助消息队列
线程AB之间通信
线程之间通信方式哪有哪些?
进程的虚拟地址空间
进程是程序运行的一次实例
什么是进程?
2的操作系统位数次幂
虚拟地址空间
代码被映射到虚拟内存
文件映射
初始化全局对象和线程
初始化其他资源
初始化
进程的加载过程?(main前发生什么)
Windbg AppVerifier PerfView
windows
gdb valgrind perf FlameGraph
linux
如何调试进程?
什么是进程和进程的加载过程
进程之间的虚拟内存是隔离的
虚拟内存加载到物理内容才可以工作
进程1虚拟空间 《= 内核共享内存 =》 进程2虚拟空间共享内存映射区 共享内存 共享内存映射区
进程间通信原理
共享内存 文件映射
Com 通信(接口形式通信,底层也是共享内存)
管道通信 (底层也是共享内存)
套接字(TCP进行编程 自己起一个端口和服务 注意杀毒软件会被封杀掉)
Windows进程间通信
共享内存 文件映射
信号
管道通信
套接字
Linux进程间通信
共享内存
视频共享类型的
两头做异步处理
多数通信是同步的
是互斥锁 2 选 1 最大的不同是在于进程 ,进程A B都持有它,进程A持有mutex 假设进程A没释放然后进程A消失或者异常退出了或者正常退出了 mutex 持有资源操作系统会作为清除,但是semaphore信号量 操作系统不会进行处理。
mutex和semaphore区别
进程间的数据同步
进程间的注意点
TCP/UDP/HTTP
gRPC
RPC
MQ(进程之间的消息队列)
跨机器通信
进程之间的通信有方哪有
进程的内存布局
栈
堆
静态存储区
TLS(线程局部存储)
mmap(内存映射)
变量类型有哪些?
重载 operator new/new[]/delete/delete[] 方法 自己来统计
如何统计内存泄露?
其中的一个方法就是我们通过New操作符 new delete 我们在堆上分配管理
堆内存管理怎么管理?
重载std::allocator 的 allocate 和 deallocate 方法 (先继承allocator 然后再重载自己的内存分配器)
如何重载STL内存分配器?
TCMalloc
STLPort
就使用第三方库
自己new一个堆对象 然后进行堆上的分配空间
是否了解其他内存分配器?
堆内存管理怎么管理
只读 (代码段 全局变量)(只写要触发就会崩溃程序)
读写 (大部分堆上的 和 堆上的)
不可读写 (只要触发就会崩溃程序)
内存访问属性有哪些?
变量的存储类型和堆的管理方法
记录起点内存镜像
开始跟踪内存
记录分配/释放 内存堆栈
让内存泄露一会
记录内存镜像
停止跟踪
内存泄露检测原理
内存泄露
堆破坏
栈破坏
句柄 GDI泄露
AppVerfier
内存检测工具 windows
(借助火焰图看可视化)
越界访问
使用未初始化 已释放内存
使用已释放文件句柄
Valgrind
FLameGraph(通过火焰图 可视化 看报告信息)
内存检测工具 Linux
如何检测内存泄露
pdb
linux:gdb
windows:windbg ide 自带的调试器
调试工具
会简单的汇编代码
看线程的堆栈(windbg -> ~*k; gdb -> thread apply all bt)
看寄存器的值 (windbg ->r xx; gdb -> info registers)
调试基本的调试命令
技能
函数返回地址被改写
什么是栈溢出?
查看所有线程堆栈,找出异常的那个
查看异常日志
尝试复现,借助工具 (valgrind AddressSanitizer AppVerifier)
如何定位?
如何定位栈溢出引发的creash?
工具
如何定位creash
要么读了不可能访问的内存
要么写了不可能写的内存
Crash的本质
空指针 堆损 栈损
可能的原因
边界检测
单元测试
野指针 检测
空指针
代码的静态检测
Coding 中
linux: valgrind
windows : AppVerifier
可执行文件动态运行检测
压力测试 放火演练(针对服务器)
疯狂点击(针对客户端)
上线前
上线前保证程序的稳定性?
如何保证程序的稳定性
windows windbg:!runaway
linux perf:perf record -g -p pid
Step1:CPU耗时在哪个线程
windows windbg:~3kb
linux gdb:thread apply id bt
Step2:看线程调用堆栈
死循环 (空语句的死循环)可以用sleep 把cpu让出去
大量计算 (比如非对称加密解密)
频繁的系统调用(用户态 和 内核态之间 的频繁 切换)
线程资源竞争
资源泄露 (内存 GDI 文件句柄 等)
CPU百分之百可能的原因?
CPU百分之百如何定义以及可能的原因
PerfView(看函数调用关系 和 函数的耗时)
PerfView(看函数调用关系 和 函数的耗时)
FlameGraph(可视化输出函数调用关系)
如何定位程序的性能瓶颈?(检测函数耗时 比如死循环)
UI/逻辑线程避免阻塞(比如可以预加载)
减少锁的使用
借助MQ异步处理
写高性能的代码?
如何定位程序的性能瓶颈?(检测函数耗时 比如死循环)
windbg ~*k
gdb thread apply all bt
pstack pid
多次查看所有线程的堆栈
如何定位死锁?
锁定与非锁定 mutex critical_section(windows 下的互斥锁)
互斥锁
数量 semaphore 进程退出时表现
信号量
线程主动询问锁的状态,占用cpu的时间,避免线程的开销
自旋锁
用于读多写少,提升 并发
读写锁
搭配互斥锁使用,条件发生时触发
条件变量
锁的分类
多个线程无法共享同一个资源
互斥
持有资源A,等待资源B
持有并等待
线程持有资源不释放时候,其他线程无法获取
不可剥夺
线程等待资源时候,形成环形链
环路等待
死锁的发生条件
最常见的是方法是资源有序分配
破坏4个条件之一
线程A ====》》》 消息队列 ===》》 线程B
基础库使用锁
业务逻辑,实现无锁线程(比如利用消息队列)
从架构上避免
如何解决?
很被动,业务复杂难免死锁再次发生
避免死锁
如何防止死锁的发生
内存管理
第五章 系统底层
3,与某给在线用户进行点对点的聊天 (目的id + 源id + 数据内容)(发送:0x02 0x13 目的id + 源id +数据内容 0x03)
2,获取在线用户链表 ((返回:0x02(开头) 0x12 0x03(结尾))
1. 发送登录信息 (发送:0x02(开头) 0x11 0x03(结尾))
功能
Qt + QTcpSocket
2,遍历一遍链表,将在线用户id号全部返回给客户端(返回:0x02 0x12 id0 id1 ... ... idN 0x03) 一个id是4个字节 有多少个id然后乘4 等于数据长度
1.识别登录信息,分配一个唯一的id号,返回给对应的客户端,用链表保存登录信息。<id数据范围 0000到9999 已ascii 的方式发送 0x30 0x30 0x31 0x32 相当于 “0012”>(返回:0x02(开头) 0x11id 0x03(结尾))(大数据量用数据库存储,小项目用链表 来保存id号)
Linux +Socket
心跳包机制,相隔一段时间没有收到,就关闭套接字
C/S <设计的应用层协议>
仿QQ (采用C/S模型)
主窗口可以是QMainWindow
在中央窗口上绘制动画,重写PaintEvent事件处理函数,开多线程处理
游戏的数据,场景宽高,蛇的速度,游戏状态,蛇有效移动位置,食物有效布局位置
控制部分,通过实现按键事件的处理函数来实现游戏控制
流程
GameSnake
项目问题
CA 让 CB 去买可乐,CB是否买到了都要通知CA
场景
CA 让 CB 去买可乐,CB是否买到了都要通知CA
接口方式解耦(一对多)
函数绑定解耦(一对一)
相互依赖的两个类如何解耦?
创建型
组合,外观,装饰,适配器,代理
结构型
策略,命令,迭代器,观察者
行为型
设计模式分类
棋牌游戏C/S通信
外观模式
观察者模式客户端(缺点可能会消息爆炸,目录结构要管理好,优点是可以解耦)
观察者:MQ(生产者&消费者)
观察者
借助第三者
AB之间解耦的共同点
介绍一下常用的设计模式
绘图在UI线程
业务在逻辑线程
业务线程无锁
耗时在工作线程
客户端开发线程模型
网页内核以外的部分
标签页 地址栏 菜单 工具栏 收藏栏 历史记录栏 等等
依赖分析
UI和UI解耦
UI和逻辑解耦
逻辑层功能分层
解耦推导
浏览器客户端架构设计
类之间解耦
优点
消息爆炸(通过分层来防止消息混乱)
缺点
优点缺点
设计
浏览器客户端设计
Redis server 随便使用
MySQL 若干台
目前有几百G的视频资料,后续会持续增加到几个T,如何设计服务提供查询?
内存 削峰
高并发?
单个程序崩溃不影响业务
可靠性?
扩容对业务无感
可扩展?
后台考虑三个点?
视频信息查询后台设计
进入大厅
报名参赛
斗地主赛事后台的设计
消息时序
消息同步
分布式 or 集中
TCP or Http
游戏中
特点分析
1,server crash 如何保证服务可用性?
2,人数增加,如何动态扩展?
斗地主赛事架构
斗地主赛事后台设计
项目是做的什么
业务背景
为什么这么选型(一定要结合业务特点)
技术架构,优缺点
角色,困难,成长
第六章 项目
面试宝典
建议
第七章 结束
QApplication
QPushButton
QLabel
QLineEdit
QTextEdit
QMainWindow
QDialog
QWidget(它是多重继承)
QLayout
QFile
QThread
QAction
QObject
QWidget
QPixmap
QImage
QPicture
QPaintDevice
QString
QSize
QPoint
QFont
QColor
QByteArray
QIcon
QDataStream
QMutex
QSemaphore
QBrush
数据类
归类
继承QObject 给它继承一个父节点或者父对象,在析构函数里面打印一句话看看有没有调用就知道内存管理有没有用了。
Qt内存管理是怎么实现的?
信号与槽函数需要几个步骤?
Qt里面的所有项目都是通过QMake进行来管理组织的,QMake文件可以解析成MakeFile,MakeFile里面填写了项目所需的文件库,然后再通过Make命令来生成可执行程序,.pro文件属于QMake的工程文件。
Qt的编译机制?
exec()主要函数
QApplication(单实例)
QPushbutton
QHBoxLayout
QVBoxLayout
QGridLayout
QObjecet
QString
单独的类不继承任何基类
类图
继承QDialog并且调用exec
怎么显示模态窗口?
第一个普通窗口是继承于widget第一种情况是不指定父窗口的情况下也不调用show这样是不显示的,第二种情况是不指定父窗口的情况下调用show是顶级窗口来显示的,第三种指定父窗口不调用show是嵌套方式显示的,第四种指定父窗口并且调用show函数还是嵌套方式显示的,不能以模态窗口显示因为没有exec。第二个QDialog这种窗体如果不指定父窗口也不调用show是不显示的,不指定父窗口但是调用了show也是已顶级窗口显示,当他指定了父窗口不调用show是没嵌套父窗口上面,当他指定了父窗口调用了show还是已顶级窗口显示还多了一个exec模态窗口来显示。
普通窗口和显示Dialog窗口不同?
第二种继承至QObject 实现槽函数 QThread对象 然后moveToThread 连接信号与槽
多线程在Qt的开启方式?
int a;a=12;//是原子操作
a++;//不是原子操作
低于32位都是原子操作
比如读写锁,读时共享,写时独占
互斥锁效率会低,只有一个线程在运行,其他线程都在等待
原子操作不会被打断,不是原子操作需要锁来保证不会出现错误。
QGraphicsScene QGraphicsItem
model
view(QGraphicsView)
controller (用户输入事件)
图形视图框架 MVC
QGraphicsView
QGraphicsScene
QGraphicsLineItemQGraphicsRectItemQGraphicsElipseItemQGraphicsSimpleTextItemQGraphicsPixmapItem
QGraphicsItem
图形视图框架 层级
什么是原子操作?
QVideoWidget
QMediaBindableInterface
ItemAtselectedItemsitemsBoundingRectsetSceneRectrender 打印场景
QMediaPlayer
QMediaPlaylist
QGraphicsVideoItem
setFlagcontainscollidesWithItemscene
QGraphicsLineItemQGraphicsRectItemQGraphicsPixmapItemQGraphicsSimpleTextItem
层级
view QTableView <= model QStanderItemModel <=controller QTableView QItemDelegate(代理能创建QLineEdit QSprinBox QDateEdit)
想显示一个表单可以有两种方式显示:1.MVC显示方式用QTableView2.非MVC显示方式用QTableWidget
QTableView
Qt
C/C++ myls
收藏
0 条评论
回复 删除
下一页