网络相关的面试题

网络相关的面试题

  • 服务器端不调用accept会发生什么

不调用accept时,也能建立连接,即三次握手完成。但不能进行API的控制,即不能进行继续通讯。以及建立好连接的队列大大小为:backlog。从而在Unix系统服务器中,若客户端调用 connect() ,客户端连接超时失败。而在Linux系统中,若客户端调用 connect()。TCP 的连接队列满后,Linux 服务器不会拒绝连接,只是有些会延时连接,有些立刻连接。

详情参考https://blog.csdn.net/hycxag/article/details/82974484

  • 浏览器中输入www.baidu.com,按回车键以后做了哪些操作

  • 先要解析出www.baidu.com域名对应的ip地址

  1. 先要知道主机默认的网关MAC:即使用ARP来获取默认网关的MAC地址。
  2. 组织数据,发送给默认网关(IP对应的时DNS服务器,而MAC地址是默认网关的MAC地址)
  3. 默认网关拥有转发数据的能力,把数据转发给路由器
  4. 路由器根据自己的路由协议,来选择一个合适的较快的路径转发数据给目的网关
  5. 目的网关(DNS服务器所在的网关)把数据发给DNS服务器
  6. DNS服务器查询解析出www.baidu.com域名对应的IP地址,并把此IP地址组织成数据包,按原路返回方式,发给请求这个域名的客户端
  • 得到www.baidu.com对应的IP地址以后,会发送TCP的三次握手进行连接
  • 连接成功后,使用http协议发送请求数据给web服务器
  • web服务器收到数据请求之后,通过查询自己的服务器得到相应的结果,并原路返回给浏览器
  • 浏览器接收到数据之后,通过浏览器自己的渲染功能来显示这个页面
  • 浏览器关闭TCP连接,即四次挥手。
  • 端口号与进程号的区别

os为了区分进程,os会分配一个pid来识别进程。但两台电脑进行交互的户的时候,很难获取另外一台电脑运行进程的pid。故需要引入另外一种区分进程的方法——端口,每个进程的端口号一般是固定的,从而可以进两台电脑进行交互。(若人为更改进程的端口号,则常规的两台电脑交互会失败) 。故pid用于一台电脑区分进程,端口号是为了多台电脑交互时,来区分进程 。

端口号分配占用2个字节:故编号为0到65535。而知名的端口号在0-1023,例如:80端口:http服务器;21端口:ftp服务器;69端口:tftp服务器。动态端口(不固定分配某种服务,而是动态分配 ):从1024到65535。用netstat -an来查看进程的端口号。

  • TCP和UDP的区别

  1. TCP提供面向连接的传输,通信前要先建立连接(三次握手机制);UDP提供无连接的传输,通信前不需要建立连接。
  2. TCP提供可靠的传输(有序(序列号),无差错(校验和),不丢失(超时重传),不重复(序列号));UDP提供不可靠的传输。
  3. TCP面向字节流的传输,因此它能将信息分割成组,并在接收端将其重组;UDP是面向数据报的传输,没有分组开销。
  4. TCP提供拥塞控制和流量控制机制;UDP不提供拥塞控制和流量控制机制。
  • 流量控制和拥塞控制的实现机制

TCP采用大小可变的滑动窗口机制实现流量控制功能。窗口的大小是字节。在TCP报文段首部的窗口字段写入的数值就是当前给对方设置发送窗口的数据的上限。

在数据传输过程中,TCP提供了一种基于滑动窗口协议的流量控制机制,用接收端接收能力(缓冲区的容量)的大小来控制发送端发送的数据量。

采用滑动窗口机制还可对网络进行拥塞控制,将网络中的分组(TCP报文段作为其数据部分)数量维持在一定的数量之下,当超过该数值时,网络的性能会急剧恶化。传输层的拥塞控制有慢开始(Slow-Start)、拥塞避免(Congestion Avoidance)、快重传(Fast Retransmit)和快恢复(Fast Recovery)四种算法。
拥塞: 大量数据报涌入同一交换节点(如路由器),导致该节点资源耗尽而必须丢弃后面到达的数据报时,就是拥塞。

  • 滑动窗口机制

TCP 采用大小可变的滑动窗口进行流量控制。窗口大小的单位是字节。在 TCP 报文段首部的窗口字段写入的数值就是当前给对方设置的发送窗口数值的上限。发送窗口在连接建立时由双方商定。但在通信的过程中,接收端可根据自己的资源情况,随时动态地调整对方的发送窗口上限值(可增大或减小)。

  • 重传机制

TCP每发送一个报文段,就设置一次定时器。只要定时器设置的重发时间到而还没有收到确认,就要重发这一报文段。 在TCP环境中,报文往返时间不定、有很大差别,例如:A、B在一个局域网络,往返时延很小;A、C在一个互联网内,往返时延很大。因此,A很难确定一个固定的、与B、C通信都适用的定时器时间

TCP采用了一种自适应算法。这种算法记录每一个报文段发出的时间,以及收到相应的确认报文段的时间。这两个时间之差就是报文段的往返时延。将各个报文段的往返时延样本加权平均,就得出报文段的平均往返时延T。

  • time_wait状态产生的原因,危害,如何避免

  • 如何产生:首先调用close()发起主动关闭的一方,在发送最后一个ACK之后会进入time_wait的状态,也就说该发送方会保持2MSL时间之后才会回到初始状态。MSL值得是数据包在网络中的最大生存时间。产生这种结果使得这个TCP连接在2MSL连接等待期间。
  • 产生的原因:
  1. 为实现TCP全双工连接的可靠释放:假设发起主动关闭的一方(client)最后发送的ACK在网络中丢失,由于TCP协议的重传机制,执行被动关闭的一方(server)将会重发其FIN,在该FIN到达client之前,client必须维护这条连接状态,也就说这条TCP连接所对应的资源(client方的local_ip,local_port)不能被立即释放或重新分配,直到另一方重发的FIN达到之后,client重发ACK后,经过2MSL时间周期没有再收到另一方的FIN之后,该TCP连接才能恢复初始的CLOSED状态。
  2. 为使旧的数据包在网络因过期而消失:因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时候,来自先前的重复分组(传输分组由于超时而重发)来到server时,让它自行消失。
     
  • 危害:  在高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于TIME_WAIT状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。(在实际业务场景中,一般长连接对应的业务的并发量并不会很高。)
  • 如何避免:
  1. 首先服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。在一个非常有用的场景就是,如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时SO_REUSEADDR选项就可以避免TIME_WAIT状态。
  2. 由于time_wait状态是在主动关闭的一方出现的,所以在设计协议逻辑的时候,尽量由客户端主动关闭,避免服务端出现time_wait
  3. so_linger设置 l_onoff为非0,l_linger为0,则强制关闭套接字并断开TCP的连接,TCP将丢弃保留在套接字发送缓冲区中的任何数据并发送一个RST给对方,而不是通常的四分组终止序列,这避免了TIME_WAIT状态;
  • tcp建立连接为什么需要3次,断开为什么需要4次

建立三次需要三次的原因:由于tcp是全双工通信,若两次建立连接,发生客户端发出的第一个连接请求报文段并没有丢失,而是在某些网络节点长时间滞留了,以致延误到连接释放以后的某个时间才能到达服务端,于是客户端会再次发生一个连接请求。若服务器发出确认,建立新的连接。故服务器将会与这个客户端建立多个连接,而这些连接大多数一直等待这个客户端发数据,浪费了Socket资源。而不是4次的原因是:由于tcp是全双工通信,服务器端把两步合成了一步,这样效率进一步提高

挥手需要四次的原因:因为TCP是全双工的通信方式,即一方断开连接后,不能向另一方发送数据,但是此时另一方可以向自己发送数据,所以双方断开连接是独立的,所以需要四次。

  • tcp建立连接和断开连接的各种过程中的状态转换细节:

客户端:主动打开SYN_SENT--->ESTABLISHED--->主动关闭FIN_WAIT_1--->FIN_WAIT_2--->TIME_WAIT--->CLOSED

服务器端:LISTEN(被动打开)--->SYN_RCVD--->ESTABLISHED--->CLOSE_WAIT(被动关闭)--->LAST_ACK--->CLOSED

外加一个CLOSING,此状态是由于服务器和客户端同时进行关闭FIN_WAIT_1--->CLOSING--->TIME_WAIT--->CLOSED。

  • epoll与select的区别

当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,大概的解决方案有以下几种:

  1. 使用多进程或者多线程,但是这种方法会造成程序的复杂,而且对与进程与线程的创建维护也需要很多的开销。(Apache服务器是用的子进程的方式,优点可以隔离用户)
  2. 用一个进程,但是使用非阻塞的I/O读取数据,当一个I/O不可读的时候立刻返回,检查下一个是否可读,这种形式的循环为轮询(polling),这种方法比较浪费CPU时间,因为大多数时间是不可读,但是仍花费时间不断反复执行read系统调用。
  3. 异步I/O(asynchronous I/O),当一个描述符准备好的时候用一个信号告诉进程,但是由于信号个数有限,多个描述符时不适用。
  4. 一种较好的方式为I/O多路复用(I/O multiplexing:在没有开辟多进程,多线程以及其他方式的前提下,也能完成并发服务器的开发)。先构造一张有关描述符的列表(epoll中为队列),然后调用一个函数,直到这些描述符中的一个准备好时才返回,返回时告诉进程哪些I/O就绪。select和epoll这两个机制都是多路I/O机制的解决方案,select为POSIX标准中的,而epoll为Linux所特有的。

区别(epoll相对select优点)主要如下:

  1. select的句柄数目受限,在linux/posix_types.h头文件有这样的声明:#define __FD_SETSIZE    1024  表示select最多同时监听1024个fd。而epoll没有,它的限制是最大的打开文件句柄数目。而poll只解决select中监听套接字的上限问题,但仍然采用轮询方式。
  2. epoll的最大好处是不会随着FD的数目增长而降低效率,在selec中采用轮询处理(单进程非阻塞服务器中的for遍历编程 ),其中的数据结构类似一个数组的数据结构,而epoll是维护一个队列,直接看队列是不是空就可以了。epoll只会对"活跃"的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么,只有"活跃"的socket才会主动的去调用 callback函数(把这个句柄加入队列),其他idle状态句柄则不会,在这点上,epoll实现了一个"伪"AIO。但是如果绝大部分的I/O都是“活跃的”,每个I/O端口使用率很高的话,epoll效率不一定比select高(可能是要维护队列复杂)。
  3. 使用mmap加速内核与用户空间的消息传递。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。
  • epoll中的et和lt的区别和实现原理

epoll有2种工作方式:LT和ET。

  1. LT(level triggered)是缺省的工作方式,并且同时支持block和no-block socket.在这种做法中,内核告诉你一个文件描述符是否就绪了,然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作,内核还是会继续通知你 的,所以,这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表。
  2. ET (edge-triggered)是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述 符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致 了一个EWOULDBLOCK 错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once),不过在TCP协议中,ET模式的加速效用仍需要更多的benchmark确认。

epoll只有epoll_create,epoll_ctl,epoll_wait 3个系统调用。

  • 内存池,进程池,线程池

自定义内存池的思想通过这个"池"字表露无疑,应用程序可以通过系统的内存分配调用预先一次性申请适当大小的内存作为一个内存池,之后应用程序自己对内存的分配和释放则可以通过这个内存池来完成。只有当内存池大小需要动态扩展时,才需要再调用系统的内存分配函数,其他时间对内存的一切操作都在应用程序的掌控之中。 应用程序自定义的内存池根据不同的适用场景又有不同的类型。 从线程安全的角度来分,内存池可以分为单线程内存池和多线程内存池。单线程内存池整个生命周期只被一个线程使用,因而不需要考虑互斥访问的问题;多线程内存池有可能被多个线程共享,因此则需要在每次分配和释放内存时加锁。相对而言,单线程内存池性能更高,而多线程内存池适用范围更广。
从内存池可分配内存单元大小来分,可以分为固定内存池和可变内存池。所谓固定内存池是指应用程序每次从内存池中分配出来的内存单元大小事先已经确定,是固定不变的;而可变内存池则每次分配的内存单元大小可以按需变化,应用范围更广,而性能比固定内存池要低。

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章