复习资料a

C语言:
1、关键字:***
①栈区与堆区的区别?
②static的用法?
③无符号数和有符号数的运算
④数据类型对应值域计算
⑤break、continue、return的区别
⑥typedef与define的区别
⑦sizeof与strlen的区别
⑧volatile的用法

2、进制转换
①常见的二进制、八进制、十进制、十六进制之间的转换
②小数间的进制转换
③其他进制之间的转换

3、标识符
①标识符命名规则

4、常量与变量
①深入理解常量和变量的概念(主要结合指针指向字符串和数组名以及宏的使用)
②字符常量的几种模式:字母、数字、三位八进制数、转义字符、%%、\
③字符串与字符表示方式的区别
④宏和宏函数 ***
⑤变量模型(作为容器保存数据方向)

5、强制类型转换***
① 显式类型转换
② 隐式类型转换

6、运算符
①算术运算:/ % ++ –
②逻辑运算:截断法则(截断后部分不参与运算)
②关系运算:== !=
④赋值运算:=(区分 == )***
⑤位运算:补码运算 转码操作(原码转补码、补码转原码)
⑥三目运算:结合宏定义使用(两数求最小数、数组求大小等)***

7、输入与输出
① 函数的学习方法(man手册的使用)
② gets函数的使用
③ scanf函数和printf函数的使用(格式)

8、结构语句
①各种结构语句的注意事项
②结构语句中的 {} 使用

9、数组 ***
① 深入理解数组的定义 (保存数据的容器)
② 一维、二维数组的格式、初始化、元素调用、数组大小计算
③ 数组中的地址
④ 多维数组的推广学习
⑤ 字符数组保存数据(逐字符、整个字符串)、元素调用、数组名调用
⑥ 字符串函数学习和封装函数(strlen、strcat、strcmp、strcpy、strstr)
⑦ 冒泡排序、选择排序、二分查找封装函数

10、指针***
① 深入理解基本指针模型
② 指针的初始化与指针调用
③ 指针大小
④ const、void修饰指针
⑤ 大小端存储 (体会指针的另类使用方法)
⑥ 指针运算
⑦ 一级指针操作一维、二维数组
⑧ 字符指针、字符指针与字符数组
⑨ 指针数组
⑩ 数组指针

int p; //这是一个普通的整型变量

int p; //首先从P 处开始,先与结合,所以说明P 是一个指针,然后再与int 结合,说明指针所指向的内容的类型为int 型.所以P是一个返回整型数据的指针

int p[3]; //首先从P 处开始,先与[]结合,说明P 是一个数组,然后与int 结合,说明数组里的元素是整型的,所以P 是一个由整型数据组成的数组

int p[3]; //首先从P 处开始,先与[]结合,因为其优先级比高,所以P 是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与int 结合,说明指针所指向的内容的类型是整型的,所以P 是一个由返回整型数据的指针所组成的数组

int (p)[3]; //首先从P 处开始,先与结合,说明P 是一个指针然后再与[]结合(与"()"这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P 是一个指向由整型数据组成的数组的指针

int **p; //首先从P 开始,先与结合,说是P 是一个指针,然后再与结合,说明指针所指向的元素是指针,然后再与int 结合,说明该指针所指向的元素是整型数据.由于二级指针以及更高级的指针极少用在复杂的类型中,所以后面更复杂的类型我们就不考虑多级指针了,最多只考虑一级指针.

int p(int); //从P 处起,先与()结合,说明P 是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数,然后再与外面的int 结合,说明函数的返回值是一个整型数据

Int (*p)(int); //从P 处开始,先与指针结合,说明P 是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P 是一个指向有一个整型参数且返回类型为整型的函数的指针

int (p(int))[3]; //可以先跳过,不看这个类型,过于复杂从P 开始,先与()结合,说明P 是一个函数,然后进入()里面,与int 结合,说明函数有一个整型变量参数,然后再与外面的结合,说明函数返回的是一个指针,然后到最外面一层,先与[]结合,说明返回的指针指向的是一个数组,然后再与结合,说明数组里的元素是指针,然后再与int 结合,说明指针指向的内容是整型数据.所以P 是一个参数为一个整数据且返回一个指向由整型指针变量组成的数组的指针变量的函数

11、函数***
① 深入函数基本模型(了解每一部分的作用)
② 根据“需要用什么便添加什么”原则自造函数
③ 函数调用
④ 函数传参:值传参、地址传参、数组传参、结构体传参
⑤ 指针函数
⑥ 函数指针
⑦ malloc的使用
⑧ memset、memcpy、atoi、itoa封装函数

12、结构体***
① 深入理解结构体的模型 (结构体即数据类型)
② 结构体变量及结构体成员调用
③ 结构体指针及结构体成员调用
④ 结构体数组及结构体成员调用
⑤ 字节对齐
⑥ 共用体特点
⑦ 结构体与共用体的区别

==================================================================

Linux基础:
1、操作系统
① Linux操作系统与windows操作系统的区别?
② Linux操作系统网络搭建
③ tftp服务器与nfs服务器搭建
④ Linux下软件安装 (dpkg与apt使用)
⑤ 常用shell命令
⑥ vi中特殊命令 (查找函数名,光标跳至对应行数等)
⑦ 理解shell与应用层和底层的关系

2、C语言补充
① #include <stdio.h> 与 #include "stdio.h"区别?***
② #ifndef HELLO_H ***
#define HELLO_H

#endif
以上代码的功能
③ 条件编译
④ Makefile与模块化编程(多个函数)

3、shell编程 *

==================================================================

数据结构:
1、概念
① 各种逻辑结构、存储结构的理解***
② 线性表特点
③ 数组与链表的区别***
④ 二叉树的概念、性质***
⑤ 二叉树的应用 (遍历顺序、中缀表达式、哈弗曼树)***
⑥ 图相关概念(度)、广度、深度优先搜素算法过程*
⑦ 八大排序算法思想、过程、应用场景、时间复杂度(冒泡、选择、插入、快排、希尔、堆、桶、归并)***
⑧ 了解 平衡二叉树、红黑树、B树、B+树等

2、代码***
可以选择不同代码分函数使用文字表达实现过程或画图表示实现过程
① 顺序表默认会写
② 单链表以及单链表相关题目
③ 双向链表、循环链表
④ 队列、栈出入顺序、循环队列
⑤ 二叉树创建、非递归遍历(了解思想即可)、层次遍历
⑥ 八大排序算法(冒泡、选择、插入、快排、希尔)
⑦ hash表

==================================================================

IO进程:
1、标准IO与文件IO ***
① 文件流指针与文件描述符
文件流指针:指向file结构体的指针

    文件描述符号:进程通过struct file结构体来描述描述打开的文件,用指针描述结构体,使用struct *fd--array[]存指针,文件描述符是该数组的下标.PCB保存文件描述符,文件描述符号表的索引

    特点:遵循最小分配原则

② 系统调用和库调用
    系统调用;通过接口,用户可以使用内核提供的各种功能

    库调用;库是可执行代码的二进制形式,可以被操作系统载入内存运行,windos与linu不兼容

③ 缓存分类
    全  满了或者强制刷新,或者达到某一条件

    行   ‘\n’,或者强制刷新  数据流向:数据->流缓冲->内核缓冲区-->磁盘

    无     可以通过强制刷新实现,stderr不缓冲

④ 标准IO与文件IO的区别
    操作对象:FILE * 文件流    ,文件描述符号

    操作函数:用户操作标准库函数,系统调用内核函数

    缓冲区:带缓冲区,不带缓冲区
⑤ fopen、open、fseek、fread、fwrite、read、write、freopen函数   

#include <stdio.h>
#include <string.h>

int main()
{
FILE *pFile = fopen(“file.txt”, “rb”);
if (pFile == NULL)
{
perror (“Error opening file”);
return 0;
}
char buf[100] = { 0 };
while (!feof(pFile)) //没有到文件末尾
{
memset(buf, 0, sizeof(buf));
size_t len = fread(buf, sizeof(char), sizeof(buf), pFile);
printf(“buf: %s, len: %d\n”, buf, len);
}
fclose(pFile);
}

1、文件创建 – creat
函数原型:int creat(const char *pathname, mode_t mode);
函数参数:pathname --创建的文件名
mode --创建的方式
S_IRUSR:可读
S_IWUSR:可写
S_IXUSR:可执行
S_IRWXU:可读可写可执行
0755 --> 111 101 101
=> 文件所有者可读可写可执行,同组用户可读可执行,其它用户可读可执行。
函数作用:创建一个文件
头文件:#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
返回值:成功返回新的文件描述符,失败返回-1。

2、文件打开 – open
函数原型:int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
其中有三个参数的用于没有文件,需要创建的时候,其它情况用只有两个参数的。
函数参数:pathname --打开的文件名
flags --打开的文件方式
O_RDONLY:只读
O_WRONLY:只写
O_RDWR:读写
O_CREAT:没有则创建
O_APPEND:追加
O_TRUNC:清空文件
O_NONBLOCK:以不可阻断的方式打开
a a+ r r+ w w+

头文件:#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
返回值:成功返回新的文件描述符,失败返回-1。

3、文件读取 – read
函数原型:ssize_t read(int fd,void * buf ,size_t count);
函数参数:fd --想要读取的文件描述符
buf --存放读取的内容
count --读取的字节大小
头文件:#include<unistd.h>
返回值:正常返回实际读取到的字节数,如果返回0,表示已到达文件尾或是无可读取的数据,出错返回-1。
注意:读取的文件必须是已经存在的文件,此外文件读写位置会随读取到的字节移动。

4、文件写入 – write
函数原型:ssize_t write (int fd,const void * buf,size_t count);
函数参数:fd --想要写入的文件描述符
buf --写入的数据
count --写入的字节大小
头文件:#include<unistd.h>
返回值:成功会返回实际写入的字节数,失败返回-1,错误代码存入errno 中。

5、文件定位 – lseek
函数原型:off_t lseek(int fildes, off_t offset, int whence);
函数参数:fildes --定位的文件描述符
offset --移动位置(SEEK_SET文件开头 SEEK_CUR文件当前位置 SEEK_END文件末尾)
whence --(<0 向前,=0 当前位置,<0 向后)
头文件:#include <sys/types.h>
#include <unistd.h>
返回值:成功返回文件的当前位置到文件开头有多少个字节,出错返回-1。
⑥ 空洞文件形成与应用
offset偏移比当前文件的总长度大时,下一次的写操作就会把文件“撑大”,中间字节没有被实际写入,成为空洞,没有实际写入的字节有重复的0表示

应用于多线程下载文件等,例如迅雷下载文件

2、库
① 静态库与动态库的区别 ***
库:是指库函数,是可执行的二进制代码,可以提供函数功能,分为静态库和动态库

        静态库在编译时加载库,一次加载所有库文件,体积相对大,但是执行时不用加载,效率相对高 ,如果库改变,程序需要重新编译,后缀名为‘.a’

        动态库程序运行时,哪里需要哪里加载,体积相对小,但是执行时再加载,执行的效率相对低。 后缀名为‘.so’
② 静态库与动态库的制作流程

静态库
gcc -c file1.c
gcc -c file2.c

gcc -c fileN.c
ar -rcs libname.a file1.o file2.o … fileN.o
动态库gcc -shared -fPIC -o lib库名.so file1.c file2.c … fileN.c
使用库 gcc 文件名 -L lib_path -l库名
3、进程***
① 进程与程序的区别
组成:

② 进程的组成
③ 进程的状态转换
五态图

④ fork与vfork的区别
    拷贝内容

    执行次序

    vfork--写时复制技术。只读共享,写时复制空间

⑤ exec函数族使用
    作用:提供了一种在进程中启动另外一个程序执行的方法

        根据路径或者文件名找到可执行文件,并替代原调用进程的数据段、代码段和堆栈段,原进程除了进程号外,其他全被替换

一个进程产生一个执行新任务的进程  fork+exec

API
int execv(const char*path,char *const argr[])

path:可执行文件的路径

argv用于存放可执行文件的参数数组

系统函数:

int execve(const char *filename, char *const argv[], char *const envp[]);

  参数:filename  可执行文件名

        argv 可执行文件命名的参数列表数组

        envp 程序执行时的环境变量列表

⑥ wait与waitpid
    用法:避免僵尸进程的产生。

    pid_t wait(int* staus)

    pid_t waitpid(pid_t pid ,int* staus,0),

        pid==-1表示任意进程

        指针

        等待方式  一般为0

⑦ _exit与exit
    作用,用于关掉子进程的

    区别:前者系统调用,直接退出,不清理缓存,后者库调用,会清理Io缓存

    子进程结束三种情况:他杀、自杀、内核错误
⑧ 守护进程原理、应用、创建过程
    创建子进程   pid=fork();

    关闭父进程    exit(0);

    创建新会话    setsid();首先该进程成为会话头,其次该会话成为进程组长

    将当前工作目录改为根目录  chdir("/")

    重新设置文件权限掩码umask(0)

    关闭不需要的的文件描述符号close(文件描述符号) 

setsid();//第三步,创建新会话
chdir("/");//第四步,将当前目录改为根目录
umask(0);//第五步,重新设置文件权限掩码
for(int i=0; i<max_file; i++)
{
close(i);//第六步,关闭不需要的文件描述符
}
⑨三个“段”
数据段:存放全局变量,常数以及动态分
正文段:

   堆栈段:

4、线程***
① 进程与线程的区别
4点

② 线程的同步
        多个线程或者进程按一定顺序访问共享资源的过程

        通过信号量来实现,信号量代表可用资源的数目,常用二维信号量0和1

        采用pv 操作
        p操作:如果信号量大于0,则减少信号量,程序往下执行,访问临界资源;如果信号量为0代表资源被占用,p操作进程就会阻塞进入等待队列。sem_wait

        V操作:等待队列中没有阻塞进程,信号量增加;如果有阻塞进程,就唤醒进程和线程

        pv操作既可以实现同步,也可以实现互斥,取决于信号量的初始值。sem_post

        信号量的创建:sem_init

        p操作:sem_wait(*sem)

        v操作:sem_post(无名信号量指针)

        移除信号量:sem_destroy();

③ 线程的互斥
            采用互斥锁,全局变量  

            int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

        pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
        int pthread_mutex_destroy(pthread_mutex_t *mutex);
         int pthread_mutex_lock(pthread_mutex_t *mutex);


          int pthread_mutex_unlock(pthread_mutex_t *mutex);



                

④ 线程死锁以及避免死锁的条件   

死锁问题的避免:

线程A需要资源X,而线程B需要资源Y,而双方都掌握有对方所要的资源,这种情况称为死锁(deadlock),或死亡拥抱(the deadly embrace)。

避免死锁产生的必要条件:

(1)互斥条件:一个资源每次只能被一个进程使用。

(2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源释放。

(3)不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

避免死锁的方法(提供两种):

(1)设置等待超时,当一个线程拿起A资源,等待B资源的时候,如果等待的时间过长则超时,释放A资源,重新等待。

(2)如果线程需要AB两个资源,等待A资源的时候阻塞,然后判断B资源是否可以使用,如果B资源正在被别的线程使用,那么该线程就释放A资源,不阻塞,从新排队等待。

  ⑤ 线程安全和线程可重入

线程安全:源于多线程环境
当一个函数被多个并发进程反复调用时,他会一直产生正确的结果,称其线程安全。
多个线程访问同一个数据,不会造成数据出错,通过加锁机制来保证安全。
消息队列线程安全,内部实现锁机制
可重入:源于单线程环境
同一个函数被不同的执行流调用,当前一个流程还没有执行完,就有其他的执行流再次进入,我们称之为重入。一个函数在重入的情况下,运行结果不会出现任何不同或者任何问题,则该函数被称为可重入函数,否则是不可重入函数。
确保条件:
不在函数内部使用静态、全局数据
不返静态和全局数据,所有数据由函数的调用者提供
不调用不可重入函数
使用本地数据,通过制作全局数据的本地拷贝来保护全局数据
多用于信号处理这种函数
1)线程安全是在多个线程情况下引发的,而可重入函数可以只在一个线程的情况下
2)线程安全不一定是可重入的,而可重入函数则一定是线程安全的
3)如果一个函数中有全局变量,那么这个线程既不是线程安全的也不是可重入的
4)如果将对临界资源的访问上锁,则这个函数是线程安全的,但如果这个重入函数若锁还未释放则会发生死锁,因此是不可冲入的
5)线程安全函数能够使不同的线程访问同一块地址空间,而可重入函数要求不同的执行流对数据的操作互不影响使结果是相同的
多进程和多线程的区别:
进程是啥,线程是啥
多线程的本质是线程重入
死锁:两个或者两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞状态,如果没有外力,他们都无法进程下去,此时处于死锁状态,这些进程被称为死锁进程。
原因:系统资源不足、程序执行的问题、资源分配不当等
死锁的四个必要条件:互斥条件、请求与保持条件、不可剥夺条件、循环等待。

⑥ 线程池:
是一个阻塞队列,里边存放着提前创建的数个线程,此队列称为线程池。由于传统并多线程服务器模型采用“即创,即销”策略,由于单位时间内频繁创建,销毁多个线程,造成的消耗不可忽略,因此有了线程。提前创建,即用即取,用完放回,队满再创建,闲置再自动销毁一定数量的,回收资源
⑦线程函数
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine) (void *),void *arg);

     int pthread_join(pthread_t thread, void **retval);

        void pthread_exit(void *retval);\

        int pthread_detach(pthread_t thread);

       pthread_t pthread_self(void);

5、进程间通信方式
各自特点比较(重点掌握共享内存、消息队列)
无名管道(),有名(内核的缓存(4k)):
特点:单向流动、承载无格式的字节流

    分类:有名和无名

    用途:无名管道用于亲缘进程通信,有名管道用于用于不相关的两个进程的通信

有名管道:
信号:
进程间唯一的异步通信机制,

    信号来源:ctrl+c中断和kill,信号传递消息少 ,主要用于通知进程已经发生。

信号量:
计数器,控制多个进程对资源的访问,通常作为一种死锁机制,防止某个正在被访问的资源被其他进程访问。

消息队列:
克服信号,管道的缺点,独立于发送和接受进程,主要定向发送数据,根据消息类型进行发送。

共享内存:映射一段被进程共享的内存,由一个进程创建,但是多个进程可以共享访问。通信最快,
信号灯:配合共享内存,实现PV操作
socket:套接字,用于本地和不同主机进程之间的通信
本地套接字:单进程

==================================================================

网络:
1、基础***
① OSI七层模型(分层思想、每层名称,功能,相关协议(了解即可))
网络比较复杂,需要描述出清晰的逻辑,就需要分层
将相似的功能放在同一层,向上提供服务,接收来自下层的服务

在这里插入图片描述

物理层:IEEE802.1A
利用传输介质为数据链路层提供物理连接,实现比特流的透明传输,尽可能屏蔽掉传输介质和物理设备的差异

数据链路层:XTP压缩传输协议,SLE串行连接封装协议,ppp
负责建立和管理节点的

在物理层的比特流基础上,通过差错控制、流量控制,使得由差错的物理线路编程变成无差错的数据链路层,即提供可靠的通过物理介质传输数据的方法。

网络层:IP ICMP ARP
在数据链路层的基础上,进一步管理网络中的数据通信,负责数据包从源到宿的传递和网际互连(包PackeT)、

运输层 TCP UDP
向用户提供可靠的端到端的差错和流量控制,保证报文的正确传输,同时向高层屏蔽数据通信的细节,向用户透明的传送报文

会话层 DNS
组织协调两个会话进程之间进行通信,并对数据交换进行管理

表示层 SNMP
翻译、压缩和加密|解密

应用层 http FTP SMTP

② TCP四层模型与OSI七层模型对应关系
在这里插入图片描述

③ TCP协议与UDP协议区别

④ 三次握手与四次挥手
TCP三次握手和四次挥手的全过程
在这里插入图片描述

三次握手:
第一次握手:客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
四次握手
与建立连接的“三次握手”类似,断开一个TCP连接则需要“四次握手”。
第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可 以接受数据。
第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。
第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。
四次挥手过程中的状态:

2、TCP通信过程***
① 代码实现
TCP服务器:
fd=socket(AF_INET,SOCK_STREAM,0);
svr_addr.sin_family=AF_INET;
svr_addr.sin_port=htons(9999);
inet_pton(AF_INET,“127.0.0.1”,&svr_addr.sin_addr);
res=bind(fd,(struct sockaddr*)&svr_addr,s_len);
listen(fd,5);
cfd=accept(fd,(struct sockaddr*)&c_addr,&c_len);
send(fd,rbuf,strlen(rbuf),0);
recv(fd,sbuf,sizeof(sbuf),0);
客户端:
fd=socket(AF_INET,SOCK_STREAM,0);
res=connect(fd,(struct sockaddr*)&svr_addr,s_len);
send(fd,rbuf,strlen(rbuf),0);
recv(fd,sbuf,sizeof(sbuf),0);
UDP服务端:
sfd=socket(AF_INET,SOCK_DGRAM,0);
svr_addr.sin_family=AF_INET;
svr_addr.sin_port=htons(9999);
svr_addr.sin_addr.s_addr=INADDR_ANY;
res=bind(sfd,(struct sockaddr*)&svr_addr,s_len);
res=recvfrom(sfd,sbuf,sizeof(sbuf),0,(struct sockaddr*)&c_addr,&c_len);
sendto(sfd,rbuf,strlen(rbuf),0,(struct sockaddr*)&c_addr,c_len);
客户端:
sfd=socket(AF_INET,SOCK_DGRAM,0);
svr_addr.sin_family=AF_INET;
svr_addr.sin_port=htons(9999);
inet_pton(AF_INET,“127.0.0.1”,&svr_addr.sin_addr);
sendto(sfd,sbuf,strlen(sbuf),0,(struct sockaddr*)&svr_addr,s_len);
recvfrom(sfd,rbuf,sizeof(rbuf),0,(struct sockaddr*)&svr_addr,&s_len);
② 详细了解socket、bind、listen、accept等函数包括参数
③ 了解TCP通信流程
在这里插入图片描述

④ 了解端口复用

setsockopt(s_fd, SOL_SOCKET,SO_REUSEADDR,&on, sizeof(int));

⑤ 数据粘包处理
    因为数据是字节流形式传输没有边界,容易造成沾包

3、UDP通信***
① 代码实现
② 了解UDP通信流程

在这里插入图片描述
③ UDP如何将数据回发给客户端
4、并发服务器***
① 循环服务器与并发服务器的区别
循环服务器在同一时刻只能响应一个客户端的请求
并发服务器在同一时刻可以响应多个客户端的请求
例如:对线程模型、多进程模型、I/O多路复用模型
② IO多路复用 (重点select、epoll,了解函数参数与具体使用)
③ 并发服务器实现(IO多路复用实现、多进程、多线程实现)
IO多路复用的实现:
多进程:
多线程:
④ 了解广播与组播实现原理和流程
单播:主机之间一对一通讯,IP单播协议
1)能及时响应客户机的请求,2)针对每个客户不同的请求发送不同的数据,实现个性化服务
组播:主机一对一组的通讯模式
广播:主机之间一对所有的通信模式,成本低,但是不能提供个性服务,有线电视网
⑤IO模型
用户空间、内核空间
完整IO过程:文件从硬盘通过内核空间最终到用户空间
同步IO:拷贝过程进行阻塞
阻塞:一直等待,知道接收到数据----等待某个条件并发低,时效低
非阻塞:应用进程与内核交换,,不间断轮询,直到接收到数据-----增加时间利用率
信号驱动IO模型:先向内核注册信号处理函数,当数据准备好,给客户端发送信号,客户端(IO操作)发送接收数据请求,接收消息。
IO复用:通过一个线程管理多个socket,通过不断轮询的方式,不听的判断socket状态
异步IO:IO操作由内核完成,客户端给内核发一个IO请求,内核返回一个IO请求收到信号,客户端就不用管了,直到再次收到一个内核IO完成信号时,客户端就可以直接使用数据
阻塞:客户端连上服务器,不发送数据, 一直阻塞下去
非阻塞:客户端连上服务器,不及时发送数据,服务器相关函数立即返回,客户端就不能再发数据了
阻塞----》非阻塞
int flag;
flag = fcntl(sockfd, F_GETFL, 0);
flag |= O_NONBLOCK;
fcntl(sockfd, F_SETFL, flag);
目标:实现先来的和后来的客户端,无论什么时候都能发送数据,实现 异步响应
解决办法:多线程、多进程、IO 多路复用
多线程、过多占用资源
线程池:只适用于,短链接
5、数据库
① 数据库操作语句的使用
② 相关函数调用
③ 了解MySql、Oracel、SqlServer、sqlite各自优劣

C++:
1、基础:***
① 引用(包括常引用、引用与指针的区别)
② 函数重载 (包括默认参数的使用)
③ extern "C"的作用
④ new、delete与malloc、free的区别
⑤ 了解命名空间

2、类与对象:***
① 类与结构体的区别
② public、private、protected的区别
③ 构造函数与析构函数
④ 深拷贝与浅拷贝
⑤ this指针

3、封装:***
① static用法
② const用法
③ 友元
④ 运算符重载(所有运算符重载都能代码实现)

4、模板:
① 函数模板
② 类模板
③ 非类模板

5、继承:***
① 概念
② 公有、私有、保护继承的区别
③ 多层继承
④ 多重继承

6、多态:***
① 概念、作用
② 虚函数与纯虚函数
③ 函数重写、函数重载

7、杂项:
① explicit 、final 、inline 关键字
② 异常处理
③ 四种转换函数的区别
④ 智能指针 ***
⑤ STL库 ***
⑥ string类 ***

==================================================================
设计模式:
常见设计模式(单例、工厂、享元、观察者、策略),能实现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值