面经总结Day1

面经总结Day1

WHAT:什么是三次握手?WHY:为什么三次握手?HOW:如何三次握手?

一、TCP的三次握手与四次挥手相关问题

img

WHAT:

三次握手:首先Client(客户端)发送SYN**(同步序列编号)连接请求报文,Server(服务器)端接受后回复ACK报文(确认字符)**,并为此次连接分配资源。客户端接收ACK报文后也向服务器发送ACK报文,并分配资源,如此建立TCP连接。

  • 第一次握手:起初两端都处于CLOSED关闭状态,服务器端处于LISTEN监听状态,客户端将标志位SYN置为1,产生一个随机的序列值seq=x,并将该数据包发送给服务器此时客户端进入SYN-SENT状态,等待Server确认

  • 第二次握手:服务器端接收到数据包后由标志位SYN=1得知客户端请求建立连接,服务器端将标志位SYN与ACK都置为1,ack=x+1,随机产生一个序列值sqe=y,并将该数据包发送给客户端以确认连接请求此时服务器进入SYN_RCVD状态,此时操作系统为该TCP连接分配TCP缓存与变量。【服务器端在第二次握手时分配资源,客户端在第三次握手时分配资源】

  • 第三次握手:客户端收到数据包后,检查ACK是否为1,检查ack是否为x+1,如果全部正确,将标志位ACK置为1,ack=y+1,【注意第三次握手不需要将SYN置1】并且此时操作系统为该TCP连接分配TCP缓存与变量,并将该数据包发送给服务器端,服务器端检查ack是否等于y+1,ACK是否为1,如果均正确则连接建立成功, 此时客户端与服务器都进入ESTABLISHED状态,此时完成三次握手,随后客户端与服务器可以开始传输数据。

WHY:

为什么要进行三次握手:

1. 阻止重复历史连接的初始化:

**为了防止已失效的连接请求报文突然传送到服务器,因而产生错误。**假设这样一个场景:A发送一个请求连接报文因为网络问题长时间滞留,到第二次连接通信释放连接后才到B,这是一个失效的请求连接报文,此时B以为是A发送的新的请求连接,于是发出确认字符,如果没有三次握手,该连接建立,但是A并没有发出请求连接,所以B就会一直等待A发送确认字符,这样B等了很久,白白浪费B的资源。

2.序列号可靠同步:(TCP的可靠传输)

如果是两次握手,服务端无法确定客户端是否已经接收到自己发送的初始序列号,如果第二次握手报文丢失,那么客户端就无法知道服务端的初始序列号,那TCP的可靠性就无从谈起。

3.确认双方的收发能力

第一次握手:服务器端得到结论:客户端的发送能力,服务器的接收能力。

第二次握手:客户端得到结论:服务器的接收、发送能力,客户端的接收、发送能力正常。但是此时服务器并不能确定客户端的接收能力是否正常。

第三次握手:服务器端得到结论:客户端接收、发送能力正常,服务器端接收、发送能力正常。

综上所述:只有三次握手才能确认双方的接收与发送能力是否正常。

4.安全问题

当TCP新连接创建成功时,内核会为连接分配一系列的内存资源,如果采用两次握手就建立,会放大DDOS的攻击。浪费服务器资源。

TCP是一种可靠传输控制协议,其核心思想就是:**既要保证数据可靠传输,又要提高传输的效率,**而三次握手恰好可以满足以上两个方面的需求。

img

中断连接端可以是客户端也可以是服务器

HOW:

**四次挥手:**假设由客户端断开连接

  • 第一次挥手:假设客户端进程先向其TCP发起连接释放报文,将FIN标志位置为1,随机产生序列seq=u,将该释放数据包发送给服务器(FIN=1,seq = u), 并停止再发送数据,主动关闭TCP连接,此时客户端进入FIN-WAIT-1(终止等待1)状态,等待服务器确认。
  • 第二次挥手:服务器接收到来自客户端的连接释放报文后发送确认报文段将ACK标志位置为1,确认号ack=u+1,随机产生一个序列号v,将该数据包发送给客户端,此时服务器进入CLOSE-WAIT(关闭等待)状态,此时TCP处于半关闭状态,此时客户端到服务器的连接释放。客户端收到服务器的确认字符后,进入FIN-WAIT-2(终止等待2)状态,等待服务器发出释放连接请求。
  • 第三次挥手:服务器发出释放连接请求报文将标志位FIN与ACK置为1,确认号ack=u+1,随机产生序列号seq=w,将该数据包发送给客户端,随后服务器进入LAST-ACK(最后确认)状态等待客户端的确认
  • 第四次挥手:客户端接收到服务器连接释放报文后,对此发出确认报文,将ACK标志位置为1,确认号ack=w+1,将该数据包发送给服务器,客户端进入TIME-WAIT(时间等待)状态,此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端进入CLOSED状态。 2MSL就是一个发送和一个回复所需的最大时间。如果知道2MSL,客户端都没有在收到FIN,说明客户端推断ACK已经被接收,TCP连接正式断开。

TIME-WAIT状态中,如果TCP 客户端最后一次发送的ACK丢失,它将重新发送。TIME-WAIT状态中所需要的时间是依赖于实现方法的。**典型的值为30秒、1分钟和2分钟。**等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放掉。

WHY:

为什么连接的时候是三次握手,关闭的时候确是四次握手:

  1. 其实在TCP握手的时候,接收端发送SYN+ACK包是将一个ACK和一个SYN合并一起到一个包中,所以减少了一次包的发送,三次完成握手。
  2. 因为TCP是全双工通信,在主动关闭方发送FIN包后,接收端可能还要发送数据不能立即关闭服务器到客户端的数据通道,所以不能将服务器端的FIN与对客户端的ACK包合并发送,只能先确认ACK,然后等待服务器无需发送数据时再发送FIN包,所以需要四次挥手,进行四次数据包的交互。

我认为就是客户端与服务器都要确保在没有数据发送时,我在断开。

为什么客户端TIME_WAIT状态需要经过2MSL才能返回到CLOSE状态?

1.为了使TCP全双工连接的可靠释放

MSL指的是报文在网络中最大生存时间。在客户端发送对服务器端的FIN的确认包ACK后,这个ACK包是有可能到达不了服务器如果收不到ACK的话需要重新发送FIN包。所以客户端发送ACK包是有可能是不可达的,服务器端如果收不到ACK的话需要重新发送FIN包。

所以客户端发送ACK后需要留出2MSL时间**(ACK到达服务器+服务器发送FIN重传包,一来一回)**等待确认服务器端确实收到了ACK包。如果客户端等待了2MSL时间也没有收到服务器的重传包FIN,说明可以认为服务器已经收到了客户端发送的ACK。

2. 避免新旧连接混淆

​ 在客户端发送完最后一个ACK报文段后,在经过2MSL时间,就可以使本连接持续时间内的所有产生的报文从网络消失,使下一个新的连接中不会出现这种旧的连接请求报文。

服务器端容易收到SYN攻击?

服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN攻击,SYN攻击就是客户端在短时间内伪造大量不存在的IP地址,并向服务器端不断发送SYN包,服务器端则回复确认包,并等待客户端确认,由于源地址不存在,因此服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常SYN请求因队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。

**防范SYN攻击措施:**降低主机的等待时间使主机尽快的释放半连接占用,短时间受到某IP的重复SYN则丢弃后续请求。

二、TCP和UDP的区别

TCP优点:

​ **可靠、稳定、双工通信。**TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、堵塞控制机制,在数据传完后,还会断开连接用来节约系统资源。

TCP缺点:

​ **效率低、占用系统资源高、容易受到攻击。**TCP在传递数据之前,要先建立连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间;而且每台设备上维护所有的传输连接,事实上,每个TCP连接都会占用系统的CPU、内存等硬件资源;因为TCP有确认机制、三次握手机制,这也导致了TCP容易受到攻击。

UDP优点:

速度快,比TCP稍安全。UDP没有TCP握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态传输协议,所以在传输数据时非常快。没有TCP这些机制,UDP比较TCP而言安全性稍高。

UDP缺点:

​ **不可靠、不稳定。**因为UDP没有TCP哪些可靠的机制,在数据传递时,如果网络质量不好,就会容易丢包。

TCP与UDP的应用场合:

TCP:当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,在往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件协议。日常生活中,常见使用TCP协议的应用如下:浏览器,用的TeInet、SSH QQ文件传输

UDP:当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。日常生活中,常见使用UDP的协议应用如下:QQ语音QQ视频

TCP与UDP区别总结:

  1. TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。

  2. TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;而UDP尽最大努力交付,即不保证可靠交付。

  3. TCP面向字节流,实际上是TCP把数据堪称一连串无结构的字节流UDP是面向报文

    UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

  4. 每一条TCP连接只能是点到点的UDP支持一对一,一对多,多对一,多对多的交互通信

  5. TCP首部开销20字节,UDP首部开销小只有8字节

  6. TCP逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

【TCP套接字编程基本步骤】

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vV3ZLhSN-1626768058861)(C:\Users\mubao\AppData\Roaming\Typora\typora-user-images\image-20210527094412336.png)]

通俗地说,由TCP数据报首部结构我们知道,唯一标识一个TCP连接的结构是一个插口对,【也就是客户端ip、客户端端口、服务器端ip、服务器端端口四元组】。这个四元组结构就是一个套接字。在客户端中,我们知道自己的ip、端口(用户定义或者内核分配),也知道目的服务器的插口地址,而在服务器端的套接字只有服务器本身的插口地址,在有客户端来连接的时候配成一个新的已连接的套接字。

服务器端:

1. 创建一个套接字:调用socket()函数,将返回一个套接字描述符sockfd;
2. 为创建的套接字绑定本地插口地址:因为由socket()函数创建的套接字所包含的信息很少,只有一些协议族和类型等,并没有指定任何的地址,因此需要创建一个套接字地址结构对象,初始化后绑定到创建的套接字上,即下一步的操作。
3. 将套接字绑定到本地插口地址上:创建一个本地套接字地址结构对象     
	(sockaddr_in),然后通过bind()函数将这个对象和前面的套接字绑定。
4. 这时套接字绑定到本地插口地址上了,这个套接字是用来监听的,也就是说这个套接字是用来监听是否有指向该服务器端的连接请求,由listen()函数将这个套接字变成监听套接字。
5. 监听套接字还是不完整的,它是一个没有源端插口地址的套接字,因此当有客户端连接到该服务器端的时候,就会与监听套接字“组合”成一个完整的已连接套接字了。服务器端是通过accept()函数来创建一个已连接套接字。
【注意】区分监听套接字和已连接套接字:监听套接字是在服务器的生命期过程中一直存在的。而连接套接字是由内核为每个与服务器连接的客户端创建的。后者在完成给定客户端服务时候被关闭。
在accept()函数来读取已完成连接队列中客户端请求,如果队列为空,则使得服务器端进入休眠状态,直到由客户端请求完成连接被唤醒。此时没有客户端俩姐请求时,陷入休眠状态。

客户端:

1. 创建一个套接字:调用socket()函数,返回要给套接字描述符sockfd;
2. 这里有个需要注意的地方,就是客户端的套接字需不需要bind一个本地插口地址。一般没有这个需要。但是我们需要一个目的服务器端的插口地址,但是不是用来绑定到套接字上面,而是用来connect到服务器端。
3. 调用connect()函数后,客户端出发三次握手。发出请求到完成三次握手过程中,客户端的连接请求将进入服务器端的未完成连接队列,完成三次握手后将进入已完成连接队列中,后者将会唤醒服务器端的进程,从而继续执行accept()函 数。
然后就可以互相通信传递数据了。

【UDP套接字编程基本步骤】

**在UDP套接字程序中,客户不需要与服务器建立连接,可直接使用sendto函数给服务器发送数据报。**同样,服务器不需要接收来自客户端的连接,可直接调用recvfrom函数,等待来自某个客户的数据达到。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qmGeTIsd-1626768058863)(C:\Users\mubao\AppData\Roaming\Typora\typora-user-images\image-20210527101836755.png)]

服务器端:

1. 创建套接字描述符(socket)
2. 设置服务器IP地址和端口号(需要转换为网络字节序的格式)
3. 将套接字描述符绑定到服务器地址(bind)
4. 从套接字描述符读取来自客户端的请求并取的客户端地址(recvfrom)
5. 向套接字描述符写入应答并发送给客户端(sendto)
6. 回到步骤4,等待读取下一个来自客户端的请求。

客户端:

1. 创建套接字描述符(socket)
2. 设置服务器的IP地址和端口号(需要转换为网络字节序的格式)。
3. 向套接字描述符写入请求并发送给服务器(sendto)
4. 从套接字描述符读取来自服务器的应答(recvfrom)
5. 关闭套接字描述符(close)

三、大端与小端的概念

  1. 大端模式:Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端

    低地址------------------------------------------》高地址

    0x12|0x34|0x56|0x78

  2. 小端模式:Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端

    低地址------------------------------------------》高地址

    0x78|0x56|ox34|0x12

网络字节顺序与本地字节顺序之间的转换函数:

htonl()–“Host to Network Long”
ntohl()–“Network to Host Long”
htons()–“Host to Network Short”
ntohs()–“Network to Host Short”

四、time_wait状态如何产生,产生原因,如何避免?

1.time_wait状态如何产生?

​ 从三次握手迁移图,**首先调用close()发起主动关闭的一方,在发送最后一个ACK之后会进入time_wait的状态,也就是说该发送方会保持2MSL时间后才会回到初始状态。**MSL值是数据包在网络中的最大生存时间。产生这种结果使得这个TCP连接在2MSL连接等待期间,定义这个连接的四元组(客户端IP地址和端口,服务端IP地址和端口)不能被使用。

2.time_wait状态产生的原因

  • 为了实现TCP全双工连接的可靠释放

    略看上文

  • 为了使旧的数据包在网络因过期而消失

    略看上文

3.time_wait状态如何避免(web服务器开发中用到了这个知识点)

首先,服务器可以设置SO_REUSERADDR套接字选项(端口复用)来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。在一个非常有用的场合就是,如果你的服务器程序停止后想要立即重启,而新的套接字依旧希望使用同一端口,此时SO_REUSEADDR选项就可以避免TIME_WAIT状态。

通信死锁

概念:通信死锁,也就是两个或多个进程在发送消息时出现的死锁。进程A给进程B发了一条消息,然后进程A阻塞直到进程B返回相应。假设请求消息消失了,那么进程A在一直等着回复,进程B也会阻塞等待请求消息到来,这时候就产生了死锁。,尽管产生了死锁,但是这并不是一个资源死锁,因为 A 并没有占据 B 的资源。根据死锁的定义来说:每个进程因为等待其他进程引起的事件而产生阻塞,这就是一种死锁。

通信死锁没有完全可见的资源,所以不能通过调度的方式来避免,但是可以使用通信中一个非常重要的概念来避免超时(timeout)。在通信过程中,只要一个信息被发出后,发送者就会启动一个定时器,定时器会记录消息的超时时间,如果超时时间到了但是消息还没有返回,就会认为消息已经丢失并重新发送,通过这种方式,可以避免通信死锁。

五、守护、僵尸、孤儿进程概念

孤儿进程:

​ 指的是在其父进程执行完成或被终止后仍然运行的一类进程。由init进程收养系统的孤儿进程。

孤儿进程的作用:

​ 在现实中用户可能刻意使进程成为孤儿进程,这样就可以让它与父进程会话脱钩,成为后面会介绍的守护进程。

僵尸进程:

​ **一个子进程的进程描述符在子进程退出时不会释放,**只有当父进程通过wait()或waitpid()获取了子进程信息后才会释放。如果子进程退出,而父进程并没有调用wait()或waitpid(),那么子进程的进程描述符仍然保存在系统中,这种进程称为僵尸进程。

解决僵尸进程:

​ 因为系统所能使用的进程号是有限的,如果产生大量僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。

​ 要消灭系统中大量的僵尸进程,只需要将其父进程杀死,此时僵尸进程就会变成孤儿进程,进而被init所收养,这样init就会释放所有的僵尸进程所占用的资源,从而结束僵尸进程。

守护进程:

​ 守护进程就是后台服务进程,因为他会有一个很长的生命周期提供服务,关闭终端不会影响服务,也就是说可以忽略某些信号。

创建守护进程的步骤:

  • 调用fork(),创建新进程,它会是将来的守护进程
  • 在父进程中调用exit,保证子进程不是进程组长
  • 调用setsid()创建新的会话区
  • 将当前目录改为根目录(如果把当前目录作为守护进程目录,当前目录不能被卸载它作为守护进程的工作目录)
  • 将标准输入,标准输出,标准错误重定向到/dev/null

六、进程间的通信方式

通信概念:

进程间的通信方式比较多,首先你需要理解下面的几个概念:

  • **竞态条件:**即两个或多个线程同时对一共享数据进行修改,从而影响程序运行的正确性时,这种就被称为竟态条件(race condition)

  • **临界区:**不仅共享资源会造成竟态条件,事实上共享文件、共享内存也会造成竟态条件、那么该如何避免呢?可以用一句话来概括说明:**禁止一个或多个进程在同一时刻对共享资源(包括共享内存、共享文件等)进行读写。**换句话说,我们需要一种互斥(mutual exclusion)条件,这也就是说,如果一个进程在某种方式下使用共享变量和文件的话,除该进程之外的其他进程就禁止做这种事(访问统一资源)。

    一个好的解决方案,应该包含下面四种条件:

    1. 任何时候两个进程不能同时处于临界区
    2. 不应对CPU的速度和数量做任何假设
    3. 位于临界区外的进程不得阻塞其他进程
    4. 不能使任何进程无限等待进入临界区

os8-9.png

  • **忙等互斥:**当一个进程对资源进行修改时,其他进程必须进行等待,进程之间要具有互斥性,我们讨论的解决方案其实都是基于忙等互斥提出的。

解决方案:

进程间的通信用专业一点的术语来表示就是Inter Process Communication ,IPC它主要有下面几种通信方式

os8-10.png

  • 消息传递:消息传递是进程间实现通信和同步等待的机制,使用消息传递,进程间的交流不需要共享变量,直接就可以进行通信;消息传递分为发送方和接收方
  • 先进先出队列:先进先出队列指的是两个不想关联进程间的通信,两个进程之间可以彼此相互进程通信,这是一种全双工通信方式
  • 管道:管道用于两个相关进程之间的通信,这是一种半双工的通信方式,如果需要全双工,需要另外一个管道。
  • 直接通信:在这种进程通信方式中,进程与继承之间只存在一条链接,进程间要明确通信双方的命名。
  • 间接通信:间接通信是通信双方不会直接建立连接,而是找到一个中介者,这个中介者可能是个对象等等,进程可以在其中放置消息,并且可以从中删除消息,依此达到进程间通信的目的。
  • 消息队列:消息队列是内核中存储消息的链表,它有消息队列标识符进行标识,这种方式能够在不同的进程之间提供全双工的通信连接。
    :`先进先出队列指的是两个不想关联进程间的通信,两个进程之间可以彼此相互进程通信,这是一种全双工通信方式
  • 管道:管道用于两个相关进程之间的通信,这是一种半双工的通信方式,如果需要全双工,需要另外一个管道。
  • 直接通信:在这种进程通信方式中,进程与继承之间只存在一条链接,进程间要明确通信双方的命名。
  • 间接通信:间接通信是通信双方不会直接建立连接,而是找到一个中介者,这个中介者可能是个对象等等,进程可以在其中放置消息,并且可以从中删除消息,依此达到进程间通信的目的。
  • 消息队列:消息队列是内核中存储消息的链表,它有消息队列标识符进行标识,这种方式能够在不同的进程之间提供全双工的通信连接。
  • 共享内存:共享内存是使用所有进程之间的内存来建立连接,这种类型需要同步进程访问来相互保护。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值