面试之计算机网络-5


#对于FIN_WAIT_2,CLOSE_WAIT状态和TIME_WAIT状态?你知道多少?

  • FIN_WAIT_2:

    • 半关闭状态。

    • 发送断开请求一方还有接收数据能力,但已经没有发送数据能力。

  • CLOSE_WAIT状态:

    • 被动关闭连接一方接收到FIN包会立即回应ACK包表示已接收到断开请求。

    • 被动关闭连接一方如果还有剩余数据要发送就会进入CLOSE_WAIT状态。

  • TIME_WAIT状态:

    • 又叫2MSL等待状态。
    • 为了使被动关闭的一方正确的关闭,以及防止历史数据出现在新连接中。

#你了解流量控制原理吗?

  • 流量控制就是让「发送方」根据「接收方」的实际接收能力控制发送的数据量。

如何控制: 接收方每次收到数据包,可以在发送ACK报文时,同时告诉发送方自己的接收窗口大小还剩余多少是空闲的。

发送方收到之后,便会调整发送窗口的大小,当发送方收到接收窗口的大小为0时,发送方就会停止发送数据,并且同时开启一个定时器,每隔一段时间就发个探测报文询问接收方。如果可以,接收方就告诉他此时接受窗口的大小;如果接受窗口大小还是为0,则发送方再次刷新启动定时器。

一般情况下接收窗口 >= 发送窗口。 https://blog.csdn.net/weixin_43901865/article/details/113106417

#建立TCP服务器的各个系统调用过程是怎样的?

  • 服务器:

    • 创建socket -> int socket(int domain, int type, int protocol);

      • domain:协议域,决定了socket的地址类型,IPv4为AF_INET。

      • type:指定socket类型,SOCK_STREAM为TCP连接,SOCK_DGRAM为UDP连接。

      • protocol:指定协议。IPPROTO_TCP表示TCP协议,为0时自动选择type默认协议。

    • 绑定socket和端口号 -> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

      • sockfd:socket返回的套接字描述符,类似于文件描述符fd。

      • addr:有个sockaddr类型数据的指针,指向的是被绑定结构变量。

      • addrlen:地址长度。

1
2
3
4
5
6
7
8
9
// IPv4的sockaddr地址结构
struct sockaddr_in {
	sa_family_t sin_family;    // 协议类型,AF_INET
	in_port_t sin_port;    // 端口号
	struct in_addr sin_addr;    // IP地址
};
struct in_addr {
	uint32_t s_addr;
}
  • 监听端口号 -> int listen(int sockfd, int backlog);

    • sockfd:要监听的sock描述字。

    • backlog:socket可以排队的最大连接数。

  • 接收用户请求 -> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    • sockfd:服务器socket描述字。

    • addr:指向客户端地址结构指针。

    • addrlen:协议地址长度。

    • 注:一旦accept某个客户机请求成功将返回一个全新的描述符用于标识具体客户的TCP连接。

  • 从socket中读取字符 -> ssize_t read(int fd, void *buf, size_t count);

    • fd:连接描述字。

    • buf:缓冲区buf。

    • count:缓冲区长度。

    • 注:大于0表示读取的字节数,返回0表示文件读取结束,小于0表示发生错误。

  • 关闭socket -> int close(int fd);

    • fd:accept返回的连接描述字,每个连接有一个,生命周期为连接周期。

    • 注:sockfd是监听描述字,一个服务器只有一个,用于监听是否有连接;fd是连接描述字,用于每个连接的操作。

  • 客户机:

    • 创建socket -> int socket(int domain, int type, int protocol);

    • 连接指定计算机 -> int connect(int sockfd, struct sockaddr* addr, socklen_t addrlen);

      • sockfd客户端的sock描述字。

      • addr:服务器的地址。

      • addrlen:socket地址长度。

    • 向socket写入信息 -> ssize_t write(int fd, const void *buf, size_t count);

      • fd、buf、count:同read中意义。

      • 大于0表示写了部分或全部数据,小于0表示出错。

    • 关闭socket -> int close(int fd);

      • fd:同服务器端fd。

#TCP 协议如何保证可靠传输?

  • 建立连接(标志位):通信前确认通信实体存在。

  • 序号机制(序号、确认号):确保了数据是按序、完整到达。

  • 数据校验(校验和):CRC校验全部数据。

  • 超时重传(定时器):保证因链路故障未能到达数据能够被多次重发。

  • 流量控制:发送方根据接受方的实际接受能力控制发送的数据量。

  • 拥塞控制:当网络拥塞时,通过拥塞窗口,减少数据的发送,防止包丢失。

#UDP是什么?

提供无连接的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。UDP头部只有8个字节,包含源和目标端口号,包长度和校验和,各占16位。

#TCP和UDP的区别

image image

  1. 连接

    • TCP 是面向连接的传输层协议,传输数据前先要建立连接。
    • UDP 是面向报文的传输层协议,即刻传输数据。
  2. 服务对象

    • TCP 是一对一的两点服务,即一条连接只有两个端点。
    • UDP 支持一对一、一对多、多对多的交互通信
  3. 可靠性

    • TCP 是可靠交付数据的~~,数据可以无差错、不丢失、不重复、按序到达~~。
    • UDP 是尽最大努力交付,不保证可靠交付数据。拓展:但是我们可以基于 UDP 传输协议实现一个可靠的传输协议,比如 QUIC 协议,具体可以参见这篇文章:如何基于 UDP 协议实现可靠传输?(opens new window)
  4. 拥塞控制、流量控制

    • TCP 有拥塞控制和流量控制机制,保证数据传输的安全性。
    • UDP 则没有,即使网络非常拥堵了,也不会影响 UDP 的发送速率。
  5. 首部开销

    • TCP 首部长度较长,会有一定的开销,首部在没有使用「选项」字段时是 20 个字节,如果使用了「选项」字段则会变长(最大60字节)。
    • UDP 首部只有 8 个字节,并且是固定不变的,开销较小。
  6. 传输方式

    • TCP 是流式传输,没有边界
    • UDP 是一个包一个包的发送,是有边界的
  7. 分片不同

    • TCP 的数据大小如果大于 MSS 大小,则会在传输层进行分片,目标主机收到后,在传输层组装 TCP 数据包。
    • UDP 的数据大小如果大于 MTU 大小,则会在网络层进行分片,目标主机收到后,在网络层组装完数据,接着再传给传输层。

#补充题:封包和拆包你听说过吗?它是基于TCP还是UDP的?

封包和拆包都是基于TCP的概念。因为TCP是无边界的流传输,所以需要对TCP进行封包和拆包,确保发送和接收的数据不粘连。

  • 封包:封包就是在发送数据报的时候为每个TCP数据包加上一个包头,包含该数据包的总长度。
  • 拆包:接收方接收到报文后提取包头中的长度信息进行截取。

#UDP的特点有哪些(附赠TCP的特点)?

  • UDP是无连接的面向报文的;
  • UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态(这里面有许多参数);
  • UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等);
  • UDP支持一对一、一对多、多对多的交互通信;
  • UDP的首部开销小,只有8个字节

那么,再说一次TCP的特点:

  • TCP是面向连接的。(就好像打电话一样,通话前需要先拨号建立连接,通话结束后要挂机释放连接);
  • 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的(一对一);
  • TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达;
  • TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双方通信的数据;
  • 面向字节流。TCP中的“流”(stream)指的是流入进程或从进程流出的字节序列。“面向字节流”的含义是:虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。

#TCP对应的应用层协议

FTP:定义了文件传输协议,使用21端口. Telnet:它是一种用于远程登陆的端口,23端口 SMTP:定义了简单邮件传送协议,服务器开放的是25号端口。 POP3:它是和SMTP对应,POP3用于接收邮件,110端口。

#UDP对应的应用层协议

DNS:用于域名解析服务,用的是53号端口 SNMP:简单网络管理协议,使用161号端口 TFTP(Trival File Transfer Protocal):简单文件传输协议,69

#数据链路层常见协议?可以说一下吗?

协议名称作用
ARP地址解析协议根据IP地址获取物理地址
RARP反向地址转换协议根据物理地址获取IP地址
PPP点对点协议主要是用来通过拨号或专线方式建立点对点连接发送数据

#Ping命令基于什么协议?原理是什么?

ping是基于网络层的ICMP协议实现的。通过向对方发送一个ICMP回送请求报文,如果对方主机可达的话会收到该报文,并响应一个ICMP回送回答报文

扩展:ICMP报文的介绍。ICMP报文分为两个种类:

  1. ICMP差错报告报文,常见的有
    1. 终点不可达
    2. 时间超过
    3. 参数问题
    4. 改变路由
  2. ICMP询问报文
    1. 回送请求和回答:向特定主机发出回送请求报文,收到回送请求报文的主机响应回送回答报文
    2. 时间戳请求和回答:询问对方当前的时间,返回的是一个32位的时间戳。

#在进行UDP编程的时候,一次发送多少bytes好?

最好的情况下是数据链路层限制的MTU大小-IP层头部20字节-UDP包头部8字节的数据量进行发送,如以太网可以发送1472字节的数据。在进行Internet的UDP编程时,最好将UDP的数据长度控件在548字节(576-8-20)以内。因为UDP是不可靠的协议,应该尽量防止数据包在数据链路层分片。 https://taifua.com/udp-512bytes-limit.html

#TCP 利用滑动窗口实现流量控制的机制?

参考82 image image https://xiaolincoding.com/network/3_tcp/tcp_feature.html#%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3

#可以解释一下RTO,RTT和超时重传分别是什么吗?

  • 超时重传:发送端发送报文后若长时间未收到确认的报文则需要重发该报文。 可能有以下几种情况:发送的数据没能到达接收端,所以对方没有响应。接收端接收到数据,但是ACK报文在返回过程中丢失。接收端拒绝或丢弃数据。

  • RTO(Retransmission Time Out):重传超时时间,即从数据发送时刻算起,超过这个时间便执行重传。

    • 通常每次重传RTO是前一次重传间隔的两倍,计量单位通常是RTT。例:1RTT,2RTT,4RTT,8RTT......

    • 重传次数到达上限之后停止重传。

  • RTT(Round Trip Time):一个连接的往返时间,即数据发送时刻到接收到确认的时刻的差值。

#拥塞控制原理听说过吗?

  • 拥塞控制目的是防止数据过多注入到网络中导致网络资源(路由器、交换机等)过载。
  • TCP拥塞控制算法:
    • 慢开始 & 拥塞避免:先试探网络拥塞程度再逐渐增大拥塞窗口,呈指数增加,直到达到阀值ssthresh,这部分是慢开始过程。达到阀值后每次以 1/拥塞窗口 增长拥塞窗口大小,呈线性增加,当发生拥塞,进行超时重传或者快速重传+快速恢复。
    • 最终拥塞窗口会收敛于稳定值。

#如何区分流量控制和拥塞控制?

  • 流量控制属于通信双方协商;拥塞控制用于控制网络中的拥塞情况。

  • 流量控制需要通信双方各维护一个发送窗、一个接收窗,对任意一方,接收窗大小由自身决定,发送窗大小由接收方响应的TCP报文段中窗口值确定;拥塞控制的拥塞窗口大小变化由试探性发送一定数据量数据探查网络状况后而自适应调整

  • 实际最终发送窗口 = min{流控发送窗口,拥塞窗口}。

#常见的HTTP状态码有哪些?

五大类 HTTP 状态码

1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。

2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。

  • 200 OK」是最常见的成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的响应头都会有 body 数据。

  • 204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。

  • 206 Partial Content」是应用于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。

3xx 类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向

  • 301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。

  • 302 Found」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。

301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。

  • 304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制。

4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。

  • 400 Bad Request」表示客户端请求的报文有错误,但只是个笼统的错误。

  • 403 Forbidden」表示服务器禁止访问资源,并不是客户端的请求出错。

  • 404 Not Found」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。

5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。

  • 500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。

  • 501 Not Implemented」表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。

  • 502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。

  • 503 Service Unavailable」表示服务器当前很忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”的意思。

#服务器出现大量close_wait的连接的原因是什么?有什么解决方法?

服务器出现大量 TIME_WAIT 状态的原因有哪些?

服务器出现大量 CLOSE_WAIT 状态的原因有哪些?

close_wait状态是在TCP四次挥手的时候收到FIN但是没有发送自己的FIN时出现的,服务器出现大量close_wait状态的原因有两种:

  • 服务器内部业务处理占用了过多时间,都没能处理完业务;或者还有大量数据需要发送;或者服务器的业务逻辑有问题,没有执行close()方法
  • 客户端异常关闭连接:客户端在与服务器进行通信后,异常关闭连接,导致服务器端无法及时收到关闭连接的确认,从而进入last ack状态。

处理方法:

  • 考虑使用连接池技术
  • 修改程序里的bug

#一台机器能够使用的端口号上限是多少,是否可以修改?如果想要用的端口超过这个限制怎么办?

65536.因为TCP的报文头部中源端口号和目的端口号的长度是16位,也就是可以表示2^16=65536个不同端口号,因此TCP可供识别的端口号最多只有65536个。但是由于0到1023是知名服务端口,所以实际上还要少1024个端口号。

而对于服务器来说,可以开的端口号与65536无关,其实是受限于Linux可以打开的文件数量,并且可以通过MaxUserPort来进行配置。