面试点2
-
TCP、UDP的区别和优缺点
-
TCP面向连接的、udp是无连接的,也就是发送数据之前不需要建立连接
-
TCP提供可靠的服务,通过TCP连接传送的数据,无差错、不丢失、不重复,并且按序到达;UDP只是尽最大努力交付,不保证可靠交付;TCp通过检验和、重传标志,序号标志,滑动窗口、确认应答实现可靠传输;如丢包的重发控制,还可以对次序乱掉的分包进行顺序控制;
-
UDP具有较好的实时性,工作效率比TCp高,适用于高速传输和实时性有较高的通信或光波通信;
-
每一条tcp链接智能是点对点的,二udp支持一对一、一对多、多对一、多对多的交互通信;
-
tcp对系统资源要求比较多,udp对系统资源要求比较少;
-
-
为什么udp更具有优势
-
udp以其简单、传输快的优势越来越多的场景下取代了tcp如实时游戏;
-
网速的提升给udp的稳定性提供了可靠的网络保障,丢包率很低,如果使用应用层重传能够确保传输的可靠性
-
tcp为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程;由于其内置的系统协议栈中极难对其进行改性;
-
采用tcp一旦发生丢包,tcp会将后续的包缓存起来,等前面的包重传并接收到后再继续发送,延时会越来越大;
-
基于udp对实时性要求严格的情况下,采用自定义重传机制,能够把丢包率产生的延迟降到最低,尽量减少网络问题对游戏造成的影响;
-
-
tcp编程的步骤
//服务端 1、创建一个socket 用函数socket(); 2、设置socket 属性 用函数setsocket(); 3、绑定ip地址端口信息到socket上 用函数bind(); 4、开启监听 用listen()函数; 5、接受来自客户端的链接 用函数 accept(); 6、收发数据用 send()\ recv()\或者是 read()\ write(); 7、关闭socket close(); //客户端; 1、创建一个socket 用函数socket(); //2、设置socket 属性 用函数setsocket(); //3、绑定ip地址端口信息到socket上 用函数bind(); 4、设置要连接的对方的ip地址和端口等属性; 5、连接到服务器,用函数 connect(); 6、收发数据用send()\recv()\或者是read()\write(); 7、关闭socket close();
udp的编程步骤
//服务端 1、创建一个socket,用函数socket(); //2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind(); 4、循环接收数据,用函数recvfrom(); 5、关闭网络连接; //客户端 1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 4、设置对方的IP地址和端口等属性; 5、发送数据,用函数sendto(); 6、关闭网络连接;
-
tcp的三次握手与四次挥手 为什么要经过time_wait状态
-
time_wait状态是什么
client收到服务端发送的fin并且返回ACk的时候的状态
当处于这个状态的时候,我们无法创建新的连接,因为端口被占用
-
为什么会有time_wait状态
-
保证可靠的终止tcp连接
-
保证让迟来的tcp报文段有足够的时间被识别并丢弃;
-
-
哪一方会有time_wait
-
一般是client的状态,并且会占用port
-
有的时候产生在server端,由于服务器端转动断开连接或者发生异常
-
-
怎么避免time_wait占用资源_
-
如果是client,一般不用担心,因为client一般选用暂时port,再次创建会重新分配一个port;除非指定一个port,但是一般不这样做;
-
假设server主动关闭链接后异常终止,则由于它总是使用用一个知名serverport,所以连接的timewait状态导致它不能重新启动,只是我们能通过socket的选项so_reuseaddr来强制进程马上使用处于timewait状态的链接占用的port
-
通过socketopt设置后即使sock处于timewait状态,与之绑定的socket地址也能够马上被使用;
-
也可以通过改动内核参数来回收被关闭的socket,从而tcp不进入timewait状态;进而同意应用程序马上重用本地的socket地址;
-
-
-
局域网和互联网内两台电脑如何建立连接实现通讯
-
局域网
-
以太网:
-
通过NAT技术(网络转换技术)将局域网的ip+端口号转化成公网的ip地址+端口号;
-
-
用一个服务器server;将pc1注册到服务器(公网ip+端口号)(经过路由器1),将c1注册到服务器;
-
公网记录了 pc1和c1的ip地址和端口号,可以将c1的IP地址+端口号发送给pc1;
-
-
-
-
什么是滑动窗口
-
-
-
什么是半连接状态
-
当tcp中的一端发送关闭链接请求后;并且接收到ack请求后,这时候进入finwait2,这种状态还可以接收数据,但是不能发送数据;这时候叫做半连接状态;(能发ack但是不能发数据包了,不能写了);
-
-
如何在internet上识别唯一一个进程
-
通过ip地址+端口号;
-
-
为什么说tcp是可靠的链接 udp是不可靠的?
-
C++异常
-
异常的情况:
-
语法错误:比如变量未定义、括号不匹配、关键字错误拼写等,在编译的时候能发现的错误,这类错误能及时被编译器发现,并指出错误的原因和位置,方便改正
-
运行时错误:比如数组下标越界、系统内存不足,这类不容易发现,能编译运行;但是在运行时候出错;
-
-
异常处理的机制:
-
思想是:执行一个函数出现异常,可以不在本函数内处理,而是抛出异常;让函数的调用者直接或者间接处理这个问题;
-
3个模块 try catch throw
-
try{可能跑出的异常语句;(检查)}
-
catch(类型名【形参名】)//捕获特定的异常;可能有多个异常;
-
catch(...)//捕获所有的异常;
-
-
-
-
map的插入操作
-
[]操作符;
-
insert函数插入:
-
感觉数据类型插入
-
插入一个数据对pair
-
-
-
红黑树的一些知识
-
map、set的底层实现
-
黑平衡的
-
与2-3树的关系
-
插入操作的过程
-
向平衡二叉树一样
-
左旋转
-
右旋转
-
颜色反
-
-
-
quic协议
-
基于UDp的多路传输
-
极低的等待延时,相对于tcp的三次握手
-
是传输层协议与tcp udp、sctp
-
-
syn泛洪攻击
-
SYN是三次我手中的第一个数据报,而当服务器返回ack后,攻击者不对其进行确认,那么这个tcp就处于挂起阻塞状态,也就是所谓的半连接状态,服务器收不到再确认就会重复发送ack给攻击者;这样更加浪费服务器的资源,攻击者对服务器发送大量的这种tcp连接,优于每一个都没有完成三次握手导致服务器挂起状态而消耗cpu与内存,最终可能死机;
-
解决方法:
-
降低syn timeout时间 使得主机尽快释放半连接状态的占用;
-
syn cookie设置,短时间内收到某个ip地址的重复syn则认为收到攻击,丢弃这个请求报文;
-
-
-
http与html的区别
-
http是超文本传输协议;
-
html是超文本标记语言;
-
html在http协议下运行
-
-
http与https的区别
-
http是超文本传输协议,被用于web浏览器和服务器之间传递信息,以铭文的方式发送,不提供任何方式的数据加密,不适合传输敏感信息;
-
https:安全套接字层超文本传输协议,为了数据传输的安全,https在http的基础上加入了ssl协议,SSL协议依靠证书来验证服务器的身份,并且为浏览器和服务器之间的通信加密;
-
主要作用:建立一个信息安全通道,保证数据传输;确认网站的真实性;
-
-
二者链接方式不一样,用的端口不一样前者是80后者是443
-
http是无状态的https是有ssl+http协议构建的可进行加密传输,带身份认证的网络协议,比前者安全;
-
-
http1.0 1.1 2.0的区别;
-
-
长连接:1.0与1.1主要区别是HTTP 1.0需要使用keep-alive参数来告知服务器端要建立一个长连接,而HTTP1.1默认支持长连接。
-
节约带宽:1.1支持只发送header信息;
-
-
1.1 2.0的区别
-
多路复用
-
数据压缩:前者不支持header数据的压缩
-
服务器推送
-
-
-
hash冲突解决的三个方法
-
开放定址法:
-
线性探测再散列
-
二次探测再散列
-
伪随机探测再散列
-
-
再哈希法
-
链地址法
-
-
进程与线程
-
线程独享的资源:
-
栈
-
寄存器
-
-
共享的资源
-
堆
-
全局变量
-
静态变量
-
文件等公用资源
-
-
-
实现一个条件变量
-
拷贝构造函数和赋值函数的区别
-
构造函数,用来在创建一个类的对象的时候,对类的数据成员进行初始化和内存分配
-
拷贝构造函数是一种特殊的构造函数,用基于同一类的对象构造和初始化另一个对象
-
赋值函数:当一个类的对象向该类的另一个对象赋值时,就会用到该类的复制函数;
-
详细区别:
-
构造函数是一个对象初始化一块内存区域,这块内存就是新对象的内存区,而赋值函数是对于一个已经被初始化对像来进行赋值操作;
-
一般来说在数据成员包含知者你对象的时候,需要考虑两种不同的处理需求:
-
复制指针对象-----拷贝构造函数大多数情况下是复制
-
引用指针对象-----赋值函数是引用对象;
-
实现不一样,拷贝构造函数是一个构造函数,它调用时候是通过参数的对象初始化产生一个对象。赋值函数是把一个新的对象赋值给一个原有的对象;如果原来的对象中有内存分配要先把内存释放掉,而且要检查一下两个对象是否是不同对象,同一对象不进行任何操作直接返回;
-
-
-
-
-
如何实现可靠的udp
-
可靠的udp利用重传机制
-
但是带来了一些问题 延时和流量过大
-
采用滑动窗口进行流量控制并且采用拥塞控制
-
慢启动
-
拥塞避免
-
快重传
-
快恢复
-
-
-
-
编写string类
-
class String { public: String(const char *str = NULL); // 普通构造函数 String(const String &other); // 拷贝构造函数 ~ String(void); // 析构函数 String & operator =(const String &other); // 赋值函数 private: char *m_data; // 用于保存字符串 }; //普通构造函数 String::String(const char *str) { if(str==NULL) { m_data = new char[1]; // 得分点:对空字符串自动申请存放结束标志'\0'的空 //加分点:对m_data加NULL 判断 *m_data = '\0'; } else { int length = strlen(str); m_data = new char[length+1]; strcpy(m_data, str); } } // String的析构函数 String::~String(void) { delete [] m_data; // 或delete m_data; } //拷贝构造函数 String::String(const String &other) // 得分点:输入参数为const型 { int length = strlen(other.m_data); m_data = new char[length+1]; strcpy(m_data, other.m_data); } //赋值函数 String & String::operator =(const String &other) // 得分点:输入参数为const型 { if(this == &other) //得分点:检查自赋值 return *this; delete [] m_data; //得分点:释放原有的内存资源 int length = strlen( other.m_data ); m_data = new char[length+1]; strcpy( m_data, other.m_data ); return *this; //得分点:返回本对象的引用
-
-
以下为Windows NT下的32位C++程序,请计算sizeof的值 void Func ( char str[100] ) { sizeof( str ) = ? } void *p = malloc( 100 ); sizeof ( p ) = ? sizeof( str ) = 4 sizeof ( p ) = 4
-
完整的strcpy
-
单例模式
-
三要素
-
私有构造方法
-
私有静态引用指向自己的实例
-
以自己的实例为返回值的公有静态方法
-
-
//懒汉式 不到万不得已 不去实例化;线程不安全; class singleton { private: static singleton *p; singleton(){ //pthread_mutex_init(&mutex); } public: //static pthread_mutex_t mutex; static singleton *instance(); singleton *instance() { //pthread_mutex_lock(&mutex); if(p==nullptr) { p=new singleton(); pthread_mutex_unlock(&mutex); } return p; } }; class singleton { private: static singleton *p; singleton(){} ~singleton() { if(p==nullptr)return; delete p; p=nullptr; } public: static singleton *instance(); singleton *p=new singleton();//恶汉的体现直接实例化;不存在线程不安全 singleton instance() { return p; } };
-
-
http中get和post的区别
-
二者的底层全是tcp/ip;都是tcp链接
-
get参数通过url传递,post放在request body中;
-
get请求在url中传递的参数是有长度限制的,post没有
-
get比post更不安全,因为参数直接暴露在url中,所以不能传递敏感信息;
-
get请求只能进行url编码,而post支持多种编码方式
-
get会主动cache,而post支持多种编码方式;
-
get请求参数会被完整保留在浏览器历史记录里;而post中的参数不会被保留
-
-
get产生一个tcp数据包,post产生两个数据包;
-
-
类模板
-
//#include <bits/stdc++.h> #include<iostream> #include <vector>//容器; #include <assert.h>//断言 #include<ctime>//时间 #include<cmath>//数学 #include <string>//字符串 #include <algorithm>//算法头文件; #include<map> #include<set> #include<limits.h> using namespace std; using ll=long long; //=========main函数 template <typename T,typename T2> class Student { public: Student(T = 0, T = 0,T=0,T2=""); Student(const Student&s); bool cmp(const Student&s); //~Student(); private: T id; T age; T score; T2 name; }; template <typename T, typename T2> Student<T,T2>::Student(T id, T age, T score, T2 name) :id(id), age(age), score(score), name(name){} template <typename T, typename T2> Student<T, T2>::Student(const Student&s) { this->id = s.id; this->age = s.age; this->score = s.score; this->name = s.name; } template <typename T, typename T2> bool Student<T, T2>::cmp(const Student&s) { return this->score > s.score; } int main() { ios::sync_with_stdio(false);//取消同步 这样cin cout 更快 更接近于 scanf Student<int,string>s1(1, 18, 100, "sicaolong"); Student<int, string>s2(2, 18, 99, "xuefeixiang"); if (s1.cmp(s2)) cout << 1 << endl; else cout << 0 << endl; return 0; }
-