在这个“金秋十月”,也是一个收获的季节。各大公司在这个时候都陆续开奖了,特别是前几天团子的开奖,还是超出了很多人的预期。 当然,几家欢喜几家愁,都没关系,因为找工作本来就是一个战线较长的任务。尽管你现在只有小公司offer,或者0offer,其实都没有必要焦虑。 你只管做你的,好好进行复盘总结,面过的,就好好复盘面经,没面过的,就好好学基础知识,刷算法题,再加上持续性的投递,你一定会有满意的offer! 1、简单介绍一下webserver
Web服务器是一种软件或应用程序,负责接收客户端请求并向其提供相应的资源。它充当客户端和后端服务器之间的中介,通过HTTP协议进行通信。
Web服务器的主要功能包括:
接受和处理客户端请求:Web服务器监听指定的端口,接受来自客户端(例如浏览器)发送的HTTP请求。它解析请求,识别所需资源,并采取适当的操作来响应请求。
资源管理:Web服务器负责管理和提供各种资源,如HTML文件、图像、CSS样式表、JavaScript脚本等。它能够从磁盘上的文件系统中获取这些资源,并将其发送给客户端。
处理动态内容:除了静态资源外,Web服务器还可以与后台应用程序(如CGI脚本、PHP脚本、ASP.NET等)交互以生成动态内容。它可以将请求转发给适当的后台处理程序,并将生成的结果返回给客户端。
连接管理:Web服务器需要管理并保持与多个客户端之间的连接。它可以使用不同的策略来处理连接池、线程池或事件驱动等方式来高效地处理并发请求。
安全性和身份验证:为了保护网站和数据安全,Web服务器通常具有各种安全功能,如HTTPS支持、SSL证书配置、身份验证和访问控制等。
日志记录:Web服务器可以记录每个请求的详细信息,包括访问时间、客户端IP地址、请求路径、响应状态等。这些日志对于分析和监视网站流量以及故障排除非常有用。
常见的Web服务器软件包括Apache HTTP Server、Nginx、Microsoft IIS等。它们在性能、可靠性和扩展性方面都有不同的特点,开发人员可以根据实际需求选择适合自己项目的Web服务器。
2、这个webserver并发连接多少
这个取决于具体的web server的实现和配置。一般来说,web server可以通过多线程、多进程或异步IO等方式处理并发连接。不同的实现方式和硬件环境都会对并发连接数产生影响。有些服务器可以处理成千上万个并发连接,而另一些可能只能处理几百个。因此,并发连接数是相对灵活可调的,取决于特定情况下所使用的服务器架构和配置。
3、线程池和线程个数怎么设置
置线程池的大小需要考虑多个因素,包括系统资源、任务类型和负载情况等。以下是一些常见的设置原则:
CPU核心数:通常线程池的大小应该与CPU核心数相近或略大,这样可以最大程度地利用CPU资源。
任务类型和执行时间:如果任务属于I/O密集型,即涉及到等待外部资源(如网络请求、文件读写等),可以设置较大的线程池来充分利用CPU空闲时间。而对于计算密集型任务,由于存在CPU竞争,适当减少线程池大小可能更有效。
内存限制:每个线程都需要一定的内存开销,在确定线程池大小时要考虑系统可用内存。避免过多线程导致内存耗尽和频繁的内存交换。
平均负载:根据当前系统平均负载情况动态调整线程池大小。例如使用指标如CPU利用率、请求处理速度等来监控系统负载,根据阈值自动调整线程池大小。
总体来说,合理地设置线程池大小可以提高程序性能和资源利用率。但要注意避免过度设置导致资源浪费或系统性能下降。
4、线程模型怎么搭配epoll进行使用
在线程模型中,可以使用epoll作为事件驱动的I/O多路复用机制,以提高服务器的并发性能。
一种常见的搭配方式是,使用一个主线程负责监听新连接,并将新连接分配给工作线程处理。 具体步骤如下:
创建一个epoll实例,并设置感兴趣的事件类型(如可读事件)。
在主线程中创建监听套接字,并将其加入到epoll实例中。
进入循环,调用epoll_wait()函数等待事件发生。
当有新连接到来时,在主线程中接收连接请求,并根据一定的策略选择一个空闲的工作线程。
将新连接的套接字添加到该工作线程的epoll实例中,并设置相应的回调函数或处理逻辑。
工作线程从自己所属的epoll实例中获取就绪事件,并执行相应的操作(如读取数据、处理业务逻辑等)。
回到第3步,继续等待新事件。
这样,通过将连接分配给不同的工作线程进行处理,可以提高系统对并发请求的处理能力。
需要注意以下几点:
主线程只负责监听新连接,不直接处理具体请求。工作线程才是真正处理业务逻辑和响应客户端请求的地方。
每个工作线程都需要拥有自己的epoll实例,以避免竞争和阻塞。每个工作线程独立负责处理自己所分配的连接。
在具体实现时,还需考虑连接管理、线程池、数据同步等方面的细节。
以上是一种常见的搭配方式,根据实际情况和需求,也可以选择其他线程模型(如多线程、异步IO等)结合epoll使用。
5、怎么理解io多路复用
O多路复用是一种通过同时监听多个IO事件的机制,使得一个进程能够同时处理多个IO请求。它利用操作系统提供的select、poll、epoll等函数,在一个线程内监听多个文件描述符(socket)上是否有数据可读或可写,从而避免了使用多线程或多进程来处理并发IO请求的开销。
通过IO多路复用,可以将大量的网络连接集中到少数几个线程或进程上进行管理和处理,提高了系统的并发性能。当某个文件描述符就绪时(例如有数据可读),应用程序会得到通知并可以立即对其进行读取操作,这样就能更高效地利用CPU资源。
6、epoll的边沿触发和水平触发
在Linux中,epoll是一种高效的I/O事件通知机制。它提供了两种触发模式:边沿触发(Edge Triggered)和水平触发(Level Triggered)。
边沿触发(Edge Triggered)模式:
当文件描述符上有可读/可写事件发生时,只会触发一次通知。
如果不立即处理该事件,下次调用epoll_wait()时将不再返回该事件,直到有新的事件再次发生。
边缘触发适合于非阻塞的、以消息为单位进行处理的场景。
水平触发(Level Triggered)模式:
当文件描述符上有可读/可写事件发生时,如果没有处理完全部数据,下次调用epoll_wait()时仍然会返回该事件。
直到该文件描述符上没有待处理的数据或者被关闭才不再返回该事件。
水平触发适合于阻塞式的、基于流的传输协议,如TCP。
选择使用边沿触发还是水平触发取决于具体场景和应用需求。一般来说,在高并发且非阻塞的网络服务器中,边缘触发能够更好地控制事件通知频率和减少无效循环检查。而对于普通应用程序或者阻塞式的IO操作,水平触发则是更常见和常用的模式。
7、你两种模式都使用过,那两种使用起来有什么区别吗
边沿触发(Edge Triggered)模式和水平触发(Level Triggered)模式是在事件驱动系统中常见的两种触发方式。
区别如下:
边沿触发模式:当输入信号从低电平变为高电平或从高电平变为低电平时,会产生一个触发事件。只有在状态改变瞬间才会触发事件。例如,边沿触发模式可用于处理硬件中断信号。
水平触发模式:只要输入信号保持在指定的电平上,就会持续触发事件。无论输入信号处于何种状态,只要满足条件就会持续触发事件。例如,在网络编程中,水平触发模式可用于处理socket数据的读取。
总体而言,边沿触发更适合处理瞬时状态变化的场景,而水平触发则更适合连续性地监测和响应特定状态。
8、有观察过这两种的区别从连接到传数据(没有)
边沿触发(Edge Triggered)和水平触发(Level Triggered)是指在数字电子系统中用于触发事件的不同方式。
在边沿触发模式下,只有在输入信号的状态从低电平到高电平或者从高电平到低电平的瞬间时,才会产生触发事件。换句话说,只有在信号变化的边沿时刻才会被触发。
而在水平触发模式下,只要输入信号保持为高电平或者低电平状态,就会持续地产生触发事件。无论输入信号是否有变化,在达到预设的水平时都会触发事件。
区别主要体现在连接和传输数据方面:
连接:对于边沿触发模式,通常需要一个外部时钟或者专门的边沿检测器来检测输入信号的变化,并将结果传递给系统。而水平触发模式则可以直接使用输入信号作为事件的条件。
传输数据:在边沿触发模式下,当边沿变化时才会进行数据传输。而在水平触发模式下,一旦满足了预设条件,数据传输就会立即开始。
9、有观察过http的包吗(没有)
是的,我可以观察和解析HTTP的包。HTTP(Hypertext Transfer Protocol)是一种用于在Web浏览器和Web服务器之间传输数据的协议。通过分析HTTP包,我们可以了解请求和响应的头部信息、请求方法、URL、状态码等内容,以及实际传输的数据。这对于网络调试、安全分析和性能优化都非常有用。
10、有看过http的报文的头吗(回答了一下对应的头的内容)
HTTP报文的头部包含了一些重要的信息。通常有以下几个常见的头字段:
请求行:包含了请求方法(GET、POST等)、URI路径和HTTP协议版本。
响应行:包含了响应状态码和对应的状态描述。
请求头:包含了客户端向服务器发送请求时附带的各种信息,例如User-Agent、Accept、Content-Type等。
响应头:包含了服务器返回给客户端的响应相关信息,例如Server、Content-Type、Content-Length等。
实体头:包含了实体主体部分(可选)的附加信息,例如Content-Encoding、Last-Modified等。
通过解析这些报文头部可以获得请求或响应的相关信息,以便进行适当的处理和解析。
11、除了Get和post其他方法见过吗(没有)
除了常见的GET和POST方法,还有一些其他HTTP请求方法,例如:
PUT:用于创建或更新资源。通常用于向服务器发送数据,并将其存储在指定的URI下。
DELETE:用于删除指定的资源。
PATCH:用于部分更新资源。与PUT不同,PATCH仅对资源进行部分更改。
HEAD:类似于GET请求,但只返回响应头信息,而不返回实际内容。
OPTIONS:获取目标URL所支持的通信选项。
这些是HTTP协议中常见的一些请求方法。具体使用哪个方法取决于你要实现的功能和服务端的支持情况。
12、get和post有什么区别吗
GET和POST是HTTP协议中两种常用的请求方法,它们在以下几个方面有区别:
1. 参数传递方式:GET请求通过URL参数传递数据,参数会附加在URL的末尾;而POST请求将数据放在请求体中进行传递,不会显示在URL上。
2. 数据大小限制:由于GET请求将参数暴露在URL上,因此对于数据大小有限制。而POST请求没有明确的大小限制,可以传递大量的数据。
3. 安全性:由于GET请求参数直接暴露在URL上,所以相对来说比较不安全,容易被拦截和篡改。POST请求把参数放在请求体中,相对更安全一些。
4. 缓存机制:GET请求默认可缓存结果,浏览器会缓存返回的页面或资源;而POST请求默认不可缓存。
13、URL组成,uri是什么
URL(Uniform Resource Locator)是统一资源定位符的缩写,它是用来标识和定位互联网上资源的字符串。一个完整的URL通常包括以下几个部分:
协议(Protocol):指示要使用的传输协议,如HTTP、HTTPS、FTP等。
主机名(Hostname):表示资源所在的主机或服务器的名称。
端口号(Port number):可选项,指定访问服务器时所使用的端口号,默认根据协议自动确定。
路径(Path):指示服务器上特定资源的路径或位置。
查询参数(Query parameters):可选项,用于传递额外的参数给服务器。
锚点(Anchor):可选项,在HTML中使用锚点进行页面内导航。
URI(Uniform Resource Identifier)是统一资源标识符的缩写,它是一个用来唯一标识和引用某个资源的字符串。 URI包括两种形式:
URL(Uniform Resource Locator),可以被用来直接访问并获取某个资源;
URN(Uniform Resource Name),仅用于标识资源而不提供直接访问。
因此,URI是URL和URN的总称。
15、线程池用到那些线程间通讯
线程池通常使用以下几种线程间通讯方式:
任务队列(Task Queue):线程池中的线程从任务队列中获取待执行的任务。通过将任务放入任务队列,可以实现生产者-消费者模型,在多个线程之间传递任务。
线程同步机制:在多个工作线程同时处理任务时,可能需要使用互斥锁、条件变量等线程同步机制来保证数据的一致性和避免竞态条件。
回调函数(Callback):当一个任务完成后,可以通过回调函数将结果返回给调用方或者通知其他相关的模块。
线程间信号量(Thread Synchronization Primitives):通过信号量等同步原语,可以实现多个线程之间的协调与控制。
共享内存(Shared Memory):多个线程可以通过共享内存来进行数据交换,但需要注意对共享数据的访问控制,以避免竞态条件。
这些通讯方式可以帮助线程池中的线程协作执行任务,并且能够有效地管理和分配工作负载。具体使用哪种通讯方式取决于应用程序的需求和设计。
16、C++类型转化
在C++中,类型转换可以通过以下方式进行:
隐式类型转换(Implicit Conversion):在不需要显式指定的情况下,编译器会自动进行类型转换。例如,将一个整数赋值给浮点数类型变量时,编译器会自动进行从整型到浮点型的隐式转换。
显式类型转换(Explicit Conversion):有时需要手动指定将一个数据类型转换为另一个数据类型。C++提供了几种显式类型转换操作符:
static_cast:用于执行静态类型检查的转换,在合理范围内允许不同但相关的数据类型之间的转换。
dynamic_cast:用于执行安全向下造型(downcasting),主要用于基类和派生类之间的转换。
const_cast:用于去除常量属性或添加常量属性。
reinterpret_cast:一种底层强制类型转换,通常用于将指针或引用重新解释为其他指针或引用。
注意,在使用显式类型转换时,请确保转换是安全且符合语义逻辑。错误的使用可能导致运行时错误或未定义行为。
17、C++中的堆和栈的区别
在C++中,堆(Heap)和栈(Stack)是两种不同的内存分配方式, 它们有以下区别:
分配方式:栈上的变量是通过系统自动进行分配和释放的,而堆上的内存则需要手动进行分配和释放。
内存管理:栈内存由编译器自动管理,它会在变量超出作用域时自动释放。而堆内存需要手动分配和释放,在不再使用时必须显式地调用 delete 或 delete[] 进行回收。
大小限制:栈通常比较小,并且大小固定。而堆则没有固定大小限制,可以动态地分配所需大小的内存空间。
访问速度:由于栈上的变量是连续分配的,因此访问速度相对较快。而堆上的内存分散在各个地址上,访问速度相对较慢。
生命周期:栈上的变量生命周期受到作用域控制,当离开作用域时会自动销毁。而堆上的对象在手动释放之前一直存在。
18、指针和引用的区别
指针和引用是C++中的两个重要概念,它们都可以用于间接访问对象或变量。下面是它们的区别:
定义和使用方式:指针使用 * 来声明和解引用,而引用使用 & 来声明,不需要解引用。
空值:指针可以为空(nullptr),表示没有指向任何对象或变量,而引用必须始终引用有效的对象。
可变性:指针本身可以重新赋值为另一个地址,即改变所指向的对象或变量;而引用一旦初始化后就不能再改变所引用的对象。
对象关系:指针可以指向多个不同类型的对象,并且可以通过运算符修改所指向对象的值;而引用始终与特定类型的对象相关联,并且无法更改为引用其他类型的对象。
空间占用:通常情况下,指针需要占据内存空间来存储地址信息;而引用本质上只是原对象的一个别名,并不需要额外的空间。
19、关键字static的使用
关键字 "static" 在 C++ 中有多种用法,以下是其中几个常见的用法:
1.静态变量(Static Variables):在函数内部声明的静态变量具有静态生存期,即它们在整个程序执行期间都存在,并且只会初始化一次。例如:
void foo() { static int count = 0; // 静态局部变量 count++; cout << "Count: " << count << endl; }
2.静态成员变量(Static Member Variables):静态成员变量属于类本身而不是类的实例,并且在所有类对象之间共享。例如:
class MyClass { public: static int sharedVariable; // 静态成员变量声明 }; int MyClass::sharedVariable = 10; // 静态成员变量定义 int main() { cout << MyClass::sharedVariable << endl; // 访问静态成员变量 return 0; }
3.静态成员函数(Static Member Functions):静态成员函数属于类本身而不是类的实例,可以直接通过类名来调用,而不需要创建对象实例。例如:
class MyClass { public: static void myStaticFunction() { cout << "This is a static member function." << endl; } }; int main() { MyClass::myStaticFunction(); // 调用静态成员函数 return 0; }
除了以上几种用法,"static" 还可以用于限制变量或函数的作用域为当前文件(称为内部链接)以及在类模板中声明静态数据成员等。具体使用取决于上下文和需求。
20、webserver出现bug的debug思路
当一个Web服务器出现bug时,以下是一些常见的debug思路:
检查日志:查看服务器日志文件,特别是错误日志,以获取有关bug的更多信息。日志通常会记录请求和响应的详细信息,包括错误消息和异常堆栈跟踪。
排查输入数据:检查传递给服务器的输入数据,包括HTTP请求参数、表单数据等。验证输入数据是否符合预期,并确保它们正确解析和处理。
分步调试:使用适当的调试工具,在代码中设置断点并逐步执行程序,观察变量值的变化以及程序流程。这可以帮助您找到可能引发bug的特定代码段。
异常处理:确保适当地捕获和处理异常。对于抛出异常的部分进行详细调试,并尝试理解异常触发的原因。
代码审查:仔细审查代码逻辑、函数调用和算法实现。检查潜在的逻辑错误、边界情况和不恰当的函数使用。
环境配置检查:确认所需软件库和依赖项是否正确安装和配置。有时,问题可能与环境相关,例如缺少必要的依赖项或不正确的配置文件。
测试用例编写:编写针对各种情况的测试用例,包括正常情况和边界条件。这有助于重现bug,并确认修复是否成功。
借助工具:使用适当的工具进行性能分析、内存泄漏检测或代码覆盖率分析等。这些工具可以帮助您找到隐藏的问题或优化性能。
21、gdb使用过吗,调试过多线程吗
在使用gdb调试多线程程序时, 你可以按照以下步骤进行操作:
使用编译选项 -g 编译你的程序,以便生成调试信息。
在终端中运行 gdb your_program 命令启动gdb,并加载你的可执行文件。
运行 set follow-fork-mode child 命令设置跟踪子进程。
运行 break main 命令设置一个断点在主函数入口处(或者其他你希望设置断点的地方)。
运行 run 命令启动程序执行,当程序停在断点处时,表示已经开始调试。
使用 thread <thread-id> 命令切换到指定线程进行调试。可以使用 info threads 查看当前所有线程的信息和ID。
可以使用常见的gdb命令如 next 、 step 、 print 等来逐步执行代码,并查看变量值等信息。
注意事项:
这些是基本的操作步骤,具体根据你的实际情况和需求进行调整和扩展。
22、linux上ping命令能确认那些内容
在Linux上, 使用ping命令可以确认以下内容:
目标主机的可达性:通过发送ICMP Echo请求,ping命令会等待目标主机的回应。如果能够收到回应,则说明目标主机是可达的;否则,表示目标主机不可达。
往返延迟时间(RTT):ping命令会显示往返延迟时间,也就是从发送请求到接收响应所经过的时间。通过观察RTT可以评估网络的延迟情况。
数据包丢失率:ping命令还会显示数据包丢失率,即发送的请求中未收到响应的比例。高丢包率可能表示网络连接存在问题。
TTL(Time to Live)值:每个发送出去的ICMP Echo请求都带有一个TTL值,在经过路由器时逐渐减小。当TTL为0时,路由器将丢弃该数据包并返回一个“Time Exceeded”错误消息。
网络拓扑分析:通过连续向不同IP地址发送ping请求,并观察结果,可以获取一些关于网络拓扑结构和路由路径方面的信息。
这些是ping命令常用来确认的内容,在诊断网络连接和故障排查时非常有用。
23、ping的底层实现
Ping是一种网络诊断工具,用于测试主机之间的连通性。在底层实现上,Ping使用ICMP协议(Internet Control Message Protocol)来发送探测包并接收目标主机的响应。
具体而言,Ping的底层实现可以分为以下几个步骤:
创建一个原始套接字(Raw Socket)。
构建ICMP报文,其中包括类型字段(通常为8表示请求Echo Request,或0表示回复Echo Reply)、校验和字段、标识符、序列号等信息。
设置IP头部信息,包括源IP地址和目标IP地址。
计算校验和,并将ICMP报文发送到目标主机。
等待目标主机响应,如果收到相应的Echo Reply报文,则表示目标主机可达;如果超时未收到响应,则表示目标主机不可达。
根据收到的响应时间计算往返时间(Round Trip Time, RTT),并显示或记录结果。
需要注意的是,具体操作系统或平台上对Ping命令的实现可能有所差异,但基本原理都是通过ICMP协议进行网络连通性测试。
24、C++中map,如果key不存在,使用[]形式遍历能成功吗
在C++中,使用 [] 操作符形式访问一个map时,如果key不存在,会自动创建该key,并将其与一个默认值关联起来。因此,遍历一个map并使用 [] 形式访问时,如果key不存在,会在该位置插入新的键值对。请注意,在使用 [] 操作符访问时要确保map是可写的(非const)。
25、tcp编程常用的api
在C/C++中,进行TCP编程常用的API包括:
socket():创建套接字
bind():将套接字绑定到一个地址和端口
listen():监听传入的连接请求
accept():接受传入的连接请求并返回新的套接字
connect():建立与远程服务器的连接
send()/sendto():发送数据到已连接或未连接的套接字
recv()/recvfrom():从已连接或未连接的套接字接收数据
close():关闭套接字
这些是基本的TCP编程API,可以使用它们来实现TCP服务器和客户端程序
26、tcp三次握手、四次挥手
TCP三次握手(Three-way Handshake)是建立TCP连接的过程 ,具体步骤如下:
客户端向服务器发送一个SYN报文段,指示请求建立连接,并选择一个初始序列号。
服务器收到SYN报文段后,回复客户端一个SYN+ACK报文段,表示同意建立连接,并选择自己的初始序列号。
客户端收到服务器的SYN+ACK报文段后,再向服务器发送一个ACK报文段,确认连接建立。此时双方可以开始正式传输数据。
TCP四次挥手(Four-way Handshake)是关闭TCP连接的过程 ,具体步骤如下:
主动关闭方(一般是客户端)发送一个FIN报文段给被动关闭方(一般是服务器),表示要关闭连接。
被动关闭方收到FIN报文段后,回复一个ACK报文段进行确认。
被动关闭方进入TIME_WAIT状态,在等待一段时间(一般为两个最大报文生存时间)后才能彻底关闭连接。
主动关闭方收到ACK报文段后,也进入CLOSED状态。此时连接已经完全关闭。
这样通过三次握手建立连接和四次挥手断开连接,确保了可靠的数据传输和双方对连接状态的准确掌握。
27、输入一个url会出现那些过程
当你输入一个URL(统一资源定位符), 通常会经历以下过程:
DNS解析:计算机将URL中的域名解析为对应的IP地址,以便进行网络通信。
建立TCP连接:使用IP地址与服务器建立TCP连接,确保可靠的数据传输。
发送HTTP请求:发送HTTP请求报文给服务器,包含请求方法(GET、POST等)、路径、头部信息和可能的请求体。
服务器处理请求:服务器接收到请求后,根据路径找到相应的资源,并执行相关处理逻辑。
返回HTTP响应:服务器将处理结果封装成HTTP响应报文返回给客户端。响应报文包含状态码、头部信息和响应体(可能是HTML、图片、JSON等)。
客户端渲染:客户端接收到响应后,根据响应内容进行页面渲染或其他操作。如果是网页,则浏览器会解析HTML、CSS和JavaScript,并呈现出最终的页面效果。
28、写服务器碰到过死锁吗
死锁在服务器开发中是一个常见的问题。死锁指的是多个线程或进程因为相互等待对方所持有的资源而陷入无限等待的状态。在服务器编程中,使用多线程或多进程处理并发请求时,如果不正确地管理锁和资源,就容易导致死锁情况的发生。
解决死锁问题可以采取以下几种方法:
避免使用过多的锁:减少并发操作所需要的锁数量,尽量简化代码逻辑。
使用良好的锁策略:合理选择和管理锁,在保证数据安全性的前提下尽量减小临界区范围。
按顺序获取锁:确保每个线程按照相同的顺序获取锁,避免出现循环等待情况。
设置超时时间:为每个请求设置合理的超时时间,并在超时后释放所有占用资源,防止长时间阻塞导致整体性能下降。
使用专门工具进行分析:借助死锁检测工具来识别和解决潜在的死锁问题。
注意,在服务器开发中预防和解决死锁问题需要综合考虑系统架构、并发设计、线程安全等方面,以确保系统的稳定性和性能。
29、http和https的区别
HTTP(Hypertext Transfer Protocol)和HTTPS(Hypertext Transfer Protocol Secure)是用于在Web浏览器和服务器之间传输数据的两种协议。
安全性:最显著的区别是安全性。HTTP不加密数据传输,而HTTPS通过使用SSL(Secure Sockets Layer)或TLS(Transport Layer Security)协议对数据进行加密来保护数据的安全性。
端口号:HTTP默认使用端口号80进行通信,而HTTPS默认使用端口号443进行通信。
数据传输方式:HTTP的数据传输是明文的,可以被拦截并查看内容。而HTTPS通过加密技术保护数据传输,使得拦截者无法轻易解读或修改传输的内容。
证书要求:为了建立HTTPS连接,服务器需要具有数字证书。这个证书由受信任的证书颁发机构(CA)签发,以确认服务器身份和公钥的有效性。
30、https的认证是谁认证谁
在 HTTPS 中,认证是由第三方机构颁发的数字证书来实现的。这个机构通常被称为证书颁发机构(Certificate Authority,CA)。当网站使用 HTTPS 时,它需要向证书颁发机构申请数字证书。证书颁发机构会对网站进行验证,并签发包含公钥及其他信息的数字证书。当用户访问这个网站时,浏览器会检查该数字证书是否有效并且与域名匹配。如果验证通过,则建立安全连接。如果数字证书无效或不可信,则浏览器会给出警告提示。
因此,HTTPS 认证是由受信任的第三方机构(即证书颁发机构)对网站的身份进行认证,并确保通信过程中数据传输的安全性和完整性。
还不熟悉的朋友,这里可以先领取一份Li nux c/c++ 开发 新手学习资料包 (入坑不亏):
编程基本功扎实,掌握 C/C++/JAVA 等开发语言、常用算法和数据结构; 熟悉 TCP/UDP 网络协议及相关编程、进程间通讯编程; 了解 Python、Shell、Perl 等脚本语言; 了解 MYSQL 及 SQL 语言、编程,了解 NoSQL, key-value 存储原理; 全面、扎实的软件知识结构,掌握操作系统、软件工程、设计模式、数据结构、数据库系统、网络安全等专业知识; 了解分布式系统设计与开发、负载均衡技术,系统容灾设计,高可用系统等知识。 这里给大家推荐零声教育全网独家的【 Linux C/C++开发 】课程体系,通过原理技术+源码分析+案例分析+项目实战,全面解析Linux C/C++,8个上线项目,2W+行手写代码,全面解析: Linux C/C++开发 1、精进基石专栏 (一)数据结构与算法
随处可见的红黑树
红黑树的应用场景进程调度cfs,内存管理
红黑树的数学证明与推导
手撕红黑树的左旋与右旋
红黑树添加的实现与添加三种情况的证明
红黑树删除的实现与删除四种情况的证明
红黑树的线程安全的做法
分析红黑树工程实用的特点
磁盘存储链式的B树与B+树
磁盘结构分析与数据存储原理
多叉树的运用以及B树的定义证明
B树插入的两种分裂
B树删除的前后借位与节点合并
手撕B树的插入,删除,遍历,查找
B+树的定义与实现
B+树叶子节点的前后指针
B+树的应用场景与实用特点
B+树的线程安全做法
海量数据去重的abhloriter bitap
hash的原理与hash函数的实现
hash的应用场景
分布式hash的实现原理
海量数据去重布隆过滤器
布隆过滤的数学推导与证明
(二)设计模式
创建型设计模式
单例模式
策略模式
观察者模式
工厂方法模式与抽象工厂模式
原型模式
结构型设计模式
适配器模式
代理模式
责任链模式
状态模式
桥接模式
组合模式
(三)c++新特性
(四)Linux工程管理
2、高性能网络设计专栏 (一)网络编程异步网络库zvnet
网络io与io多路复用select/poll/epoll
socket与文件描述符的关联
多路复用select/poll
代码实现LT/ET的区别
事件驱动reactor的原理与实现
reactor针对业务实现的优点
poll封装send_ cb/recv_ _cb/ accept_ _cb
reactor多核实现
跨平台(select/epoll/kqueue)的封装reactor
redis,memcached, nginx网 络组件
http服务器的实现
reactor sendbuffer与recvbuffer封装http协议
http协议格式
有限状 态机fsm解析http
其他协议websocket, tcp文件传输
(二)网络原理
服务器百万并发实现(实操)
同步处理与异步处理的数据差异
网络io线程池异步处理
ulimit的fd的百万级别支持
sysctI. conf的rmem与wmem的调优
conntrack的原理分析
Posix API与网络协议栈
connect,listen, accept与三次握 手
listen参数backlog
syn泛洪的解决方案
close与四次挥手
11个状态迁移
大量close_ wait与time wait的原因与解决方案
tcp keepalive与 应用层心跳包
拥塞控制与滑动窗口
UDP的可靠传输协议QUIC
udp的优缺点
udp高并发的设计方案
qq早期为什么选择udp作为通信协议
udp可靠传输原理
quic协议的设计原理
quic的开源方案quiche
kcp的设计方案与算法原理
协程调度器实现与性能测试
调度器的定义分析
超时集合,就绪队列,io等待集合的实现
协程调度的执行流程
协程接口实现,异步流程实现
hook钩子的实现
协程实现mysql请求
协程多核方案分析
协程性能测试
(三)自研框架:基于dpdk的用户态协议栈的实现(已开源)
用户态协议栈设计实现
用户态协议栈的存在场景与实现原理
netmap开源框架
eth协议,ip协议, udp协议实现
arp协议实现
icmp协议实现
应用层posix api的具体实现
socket/bind/listen的实现
accept实现
recv/send的实现
滑动窗口/慢启动讲解
重传定时器,坚持定时器,time_ wait定时器,keepalive定时器
手把手设计实现epoll
epoll数据结构封装与线程安全实现
协议栈fd就绪回调实现
epoll接口实现
LT/ET的实现
高性能异步io机制io_ _uring
与epo1l媲美的io_ uring
io_ _uring系统调用io_ _uring_ setup, io_ _ur ing_ register, io_ _ur ing_ enter
liburng的io_ uring的关系
io_ uring与epoll性能对比
io_ _uring的共享内存机制
io_ uring的使用场景
io_ ur ing的accept, connect, recv, send实现机制
io_ uring网络读写
io_ uring磁盘读写
proactor的实现
3、基础组件设计专栏 (一)池式组件
(二)高性能组件
原子操作CAS与锁实现(项目)
互斥锁的使用场景与原理
自旋锁的性能分析
原子操作的汇编实现
无锁消息队列实现(项目)
有锁无锁队列性能
内存屏障Barrier
数组无锁队列设计实现
链表无锁队列设计实现
网络缓冲区设计
RingBuffer设计
定长消息包
ChainBuffer 设计
双缓冲区设计
定时器方案红黑树,时间轮,最小堆(项目)
定时器的使用场景
定时器的红黑树存储
时间轮的实现
最小堆的实现
分布式定时器的实现
手写死锁检测组件(项目)
死锁的现象以及原理
pthread_ _mutex_ lock/pthread_ _mutex_ _unlock dIsym的实现
有向图的构建
有向图dfs判断环的存在
三个原语操作 lock before, lock_ after, unlock_ after
死锁检测线程的实现
手写内存泄漏检测组件(项目)
内存泄漏现象
第三方内存泄漏与代码内存泄漏
malloc与free的dIsym实现
内存检测策略
应用场景测试
手把手实现分布式锁(项目)
多线程资源竞争互斥锁
自旋锁
加锁的异常情况
非公平锁的实现
公平锁的实现
(三)开源组件
4、中间件开发专栏 (一)Redis
Redis相关命令详解及其原理
string,set, zset, Iist,hash
分布式锁的实现
Lua脚本解决ACID原子性
Redis事务的ACID性质分析
Redis协议与异步方式
Redis协议解析
特殊协议操作订阅发布
手撕异步redis协议
存储原理与数据模型
string的三种编码方 式int, raw, embstr
双向链表的list实现
字典的实现,hash函数
解决键冲突与rehash
跳表的实现 与数据论证
整数集合实现
压缩列表原理证明
主从同步与对象模型
对象的类型与编码
广字符串对象
列表对象
哈希对象
集合对象
有序集合
类型检测与命令多态
内存回收
对象共享
对象空转时长
redis的3种集群方式主从复制,sentinel, cluster
4种持久化方案
(二)MySQL
(三)Kafka
(四)Nginx
Nginx反 向代理与系统参数配置conf原理
Nginx静态文件的配置
Nginx动态接口代理配置
Nginx对Mqtt协议转发
Nginx对Rtmp推拉流
Openresty对Redis缓存数据代理
shmem的三种实现方式
原子操作
nginx channel
信号
信号量
Nginx过滤 器模块实现
Nginx Filter模块运行原理
过滤链表的顺序
模块开发数据结构 ngx_ str_ _t,ngx_ list_ t,ngx_ buf_ t,ngx_ chain_ t
error日志的用法
ngx_ comond_ t的讲解
ngx_ http_ _module_ _t的执行流程
文件锁,互斥锁
slab共享内存
如何解决 "惊群”问题
如何实现负载均衡
Nginx Handler模块实现
Nginx Handler模块运行原理:
ngx_ module_ t/ngx_ http_ module_ t的讲解
ngx_ http_ top_ body_ filter/ngx_ http_ _top_ header_ filter的 原理
ngx_ rbtree_ t的使用方法
ngx_ rbtree自定义添加方法
Nginx的核心数据结构ngx_ cycle_ t,ngx_ event. _moule_ t
http请求的11个处理阶段
http包体处理
http响应发送
Nginx Upstream机制的设计与实现
模块性能测试
5、开源框架专栏 (一)游戏服务器开发skynet (录播答疑)
Skynet设计原理
多核并发编程-多线程,多进程,csp模型,actor模型
actor模型实现-lua服务和c服务
消息队列实现
actor消息调度
skynet网络层封装以及lua/c接口编程
skynet reactor 网络模型封装
socket/ socketchanne|封装
手撕高性能c服务
lua编程以及lua/c接口编程
skynet重要组件以及手撕游戏项目
基础接口 skynet. send, skynet. cal I, skynet. response
广播组件multicastd
数据共享组件 sharedatad datasheet
手撕万人同时在线游戏
(二)分布式API网关
(三)SPDK助力MySQL数据落盘, 让性能腾飞(基础设施)
(四)高性能计算CUDA (录播答疑)
gpu并行计算cuda的开发流程
cpu+gpu的异构计算
计算机体系结构中的gpu
cuda的环境搭建nvcc 与srun的使用
cuda的向量加法与矩阵乘法
MPI与CUDA
音视频编解码中的并行计算
cuda的h264编解码
cuda的mpeg编解码
ffmpeg的cuda支持
(五)并行计算与异步网络引擎workflow
(六)物联网通信协议mqtt的实现框架mosquitto
mqtt的高效使用场景
mqtt的 发布订阅模式
解决低带宽网络环境的数据传输
3种Qos等级
0Auth与JWT的安全认证
mctt的broker
mqtt的遗嘱机制
发布订阅的过滤器.
mosqujitto的docker部暑
matt的日志实时监控
6、云原生专栏 (一)Docker
Docker风光下的内核功能(录播答疑)
进程namespace
UTS namespace
IPC namespace
网络namespace
文件系统namesapce
cgroup的资源控制
Docker容器管理与镜像操作(录播答疑)
Docker镜像下载与镜像运行
Docker存储管理
Docker数据卷
Docker与容器安全
Docker网络管理(项目)
5种Docker网络驱动
pipework跨主机通信
0vS划分vlan与隧道模式
GRE实现跨主机Docker间通信
Docker云与容器编排 (项目)
Dockerfile的语法流程
编排神器Fig/Compose
FIynn体系 架构
Docker改变了什么?
(二)Kubernetes
k8s环境搭建(录播答疑)
k8s集群安全设置
k8s集群网络设置
k8s核心服务配置
kubectI命令工具.
yam|文件语法
Pod与Service的用法 (录播答疑)
Pod的管理配置
Pod升级与回滚
DNS服务之于k8s
http 7层策略与TLS安全设置
k8s集群管理的那些事儿(项目)
Node的管理
namespace隔离机制
k8s集群日志管理
k8s集群监控
k8s二次开发与k8s API (项目)
RESTful接口
API聚合机制
API组
Go访问k8s API
7、性能分析专栏 (一)性能与测试工具
(二)观测技术bpf与ebpf
内核bpf的实现原理
跟踪,嗅探,采样,可观测的理解
动态hook: kpr obe/ upr obe
静态hook: tr acepoint和USDT
性能监控计时器PMC模 式
cpu的观测taskset的使 用
BPF工具bpftrace, BCC
bpf对内核功 能的观测
内存观测kmalloc与vm_ area_ struct
文件系统观测vfs的状态:
磁盘io的观测bitesize, mdf lush
bpf对网络流量的统计
bpf对redis-server观测
网络观测tcp_ connect, tcp_ accept, tcp_ close
(三)内核源码机制
8、分布式架构 (一)分布式数据库
(二)分布式文件系统(录播答疑)
内核级支持的分布式存储Ceph
ceph的集群部署
monitor与OSD
ceph 5个核心组件
ceph集群监控
ceph性能调调优与benchmark
分布式ceph存储集群部署
同步机制
线性扩容
如何实现高可用
负载均衡
(三)分布式协同
注册服务中心Etcd
etcd配置服务、服务发现、集群监控、leader选举、 分布式锁
etcd体系结构详解(gRPC, WAL,Snapshot、 BoItDB、 Raft)
etcd存储原理深入剖析(B树、B+树)
etcd读写机制以及事务的acid特性分析
raft共识算法详解(leader选举+日志复制)
协同事件用户态文件系统fuse (项目)
fuse的使用场景
文件系统读写事件
fuse的实现原 理
/dev/fuse的 作用
快播核心技术揭秘P2P框架的实现(录播答疑)
网关NAT表分析
NAT类型,完全锥型NAT,对称NAT,端口限制锥形NAT,IP限制锥型NAT
代码逻辑实现NAT类型检测
网络穿透的原理
网络穿透的3种情况
9、上线项目实战 (一)dkvstore实现(上线项目)
(二)图床共享云存储(上线项目)
ceph架构分析和配置
ceph架构分析
快速配置ceph
上传文件逻辑 分析
下载文件逻辑分析
文件传输和接口设计
http接口设计
图床数据库设计
图床文件上传,下载,分享功能实现
业务流程实现
容器化docker部署
crontab定时清理数据
docker server服 务
grpc连接池管理
(三)容器化docker部署
(四)零声教学AI助手一代(上线项目)
AI助手架构设计与需求分析
chatgpt的构想 与需求分析
基于开源项目初步构建项目
gin框架实现代理服务
接口功能设计
grpc与protobuf的使用流程
token计数器与tokenizer的服务封装
敏感词识别服务
向量数据库与连接池设计
redis实现上下文管理
问题记录保存
web端协议解析
OneBot协议
服务部署上线
docker stack服务部署
wrk接口吞吐量测试
线上节点监控
(五)魔兽世界后端TrinityCore (上线项目)
网络模块实现
boost.asio跨平台网络库
boost. asio核心命名空间以及异步io接口
boost. asio在TrinityCore 中的封装
网络模块应用实践
地图模块实现
地图模块抽象: map、 area、grid、 cell
地图模块驱动方式
A0I 核心算法实现
AABB碰撞检测实现
A*寻路算法实现
战斗模块实现
技能设计以及实 现
Al设计
怪物管理
副本设计
TrinityCore 玩法实现
用户玩法实现-任务系统
数据配置以及数据库设计
触发机制实现
多人玩法实现-工会设计
10、适宜的工程师人群(共分为8大群体) 1.从事业务开发多年,对底层原理理解不够深入的在职工程师
2.从事嵌入式方向开发,想转入互联网开发的在职工程师
3. 从事Qt/MFC等桌面开发的,薪资多年涨幅不大的在职工程师
4.从事非开发岗位(算法岗,运维岗,测试岗),想转后台开发岗位的在职工程师
5.工作中技术没有挑战,工作中接触不到新技术的在职工程师
6.自己研究学习速度较慢,不能系统构建知识体系的开发人员
7.了解很多技术名词,但是深入细问又不理解的工程师
8.计算机相关专业想进入大厂的在校生(本科及以上学历,有c/c++基础)
11、配套书籍资料 1. MySQL: 《高性能MySQL 第3版》
2. Nginx: 《深入理解Nginx: 模块开发与架构分析(第2版)》(陶辉)
3. Redis: Redis设计与实现 (黄健宏)
4. Linux内核: 《深入理解Linux内核架构》 (郭旭 译)
5. 数据结构与算法:《算法导论》(第3版)
6.性能分析:《性能之巅洞悉系统、企业与云计算》
7. MongoDB: 《MongoDB权威指南》
8. Ceph: 《Ceph分布式存储学习指南》 (Ceph中国社区)
9. Docker: 《Docker容器 与容器云(第2版)》
10. TCP/IP: 《Tcp/Ip详解卷一卷二卷三》
11. Linux系统编程: 《Unix环境高级编程》
12. 计算机: 《深入理解计算机系统》
13. DPDK: 《深入浅出DPDK》
14. k8s: 《Kubernates权威指南》 龚正等编著
15. bpf: 《BPF之巅洞悉Linux系统和应用性能》
以上是系统学习课程大纲,需要系统学习请扫码添加小雯老师( 备注911 ) 领取专属大额优惠券。
学习成果检验
腾讯offer比例15%
知名企业offer比例73%
最高offer腾讯T3.1(现T9)年薪65w
最高年薪涨幅30W
最快跳槽学习时间1个半月
如果是想在c/c++开发方向得到有效的快速提升 (不是所谓的速成),这份学习体系是大家绕不过的具有参考意义的提升路线。从学习路线中可以对c/c++开发方向的技术栈有一个清晰的认识。