计算机网络个人小结

  1. 不同层的数据报的名称
    应用层: data
    TCP层: segment
    IP 层: packet
    MAC层: frame

  2. MTU vs MSS, MSL vs TTL:
    https://www.xiaolincoding.com/network/1_base/how_os_deal_network_package.html#linux-%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE%E6%A0%88

MTU:一个网络包的最大长度,以太网中一般为 1500 字节。
在以太网中,规定了最大传输单元(MTU)是 1500 字节,也就是规定了单次传输的最大 IP 包大小。
当网络包超过 MTU 的大小,就会在网络层分片,以确保分片后的 IP 包不会超过 MTU 大小,如果 MTU 越小,需要的分包就越多,那么网络吞吐能力就越差,相反的,如果 MTU 越大,需要的分包就越少,那么网络吞吐能力就越好。

MSS:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度。
注意:TCP层需要根据MSS裁剪segment大小,因为MSS已经确保了IP包不会超过MTU大小,所以IP层不需要再根据MTU裁剪。
UDP层不会根据MSS裁剪,所以用UDP的话,IP层需要根据MTU裁剪。
发送窗口和 MSS 有什么关系?
发送窗口决定了一口气能发多少字节,而 MSS 决定了这些字节要分多少包才能发完。

MSL vs TTL:
MSL 指的是 TCP 协议中任何报文在网络上最大的生存时间,任何超过这个时间的数据都将被丢弃。虽然 RFC 793 规定 MSL 为 2 分钟,但是在实际实现的时候会有所不同,比如 Linux 默认为 30 秒,那么 2MSL 就是 60 秒。
MSL 与 TTL 的区别: MSL 的单位是时间,而 TTL 是经过路由跳数。所以 MSL 应该要大于等于 TTL 消耗为 0 的时间,以确保报文已被自然消亡。

  1. Linux 常用的跟网络有关的命令
    netstat -napt 查看TCP 的连接状态。
    route -n 命令查看当前系统的路由表。
    arp -a 命令查看 ARP 缓存的内容
    ss -nli 命令查看每一个 TCP 连接的 cwnd 初始化值
    iptables -I INPUT -s 192.168.xx.xx -j DROP 客户端配置的防火墙规则
    tcpdump -i eth1 icmp and host 183.232.231.174 -nn 抓网络数据包
    -i eth1 抓eth1网口的数据包
    icmp 抓icmp协议的数据包
    host 主机过滤,抓对应IP的数据包
    -n 不解析IP地址和端口号的名称
    ethtool eth0 ethtool加网卡名,获得当前网卡支持的最大速度
    sar -n DEV 1 sar命令从网络接口层面来分析数据包的收发情况。
    sysctl net.ipv4.tcp_rmem 查看接收缓冲区
    net.ipv4.tcp_rmem = 4096 87380 6291456
    sysctl net.ipv4.tcp_wmem 查看发送缓冲区
    net.ipv4.tcp_wmem = 4096 16384 4194304
    mtr -r baidu.com mtr命令可以查看到你的机器和目的机器之间的每个节点的丢包情况。

  2. ARP and RARP
    ARP: IP->MAC 在局域网中广播IP地址,若某设备IP地址match,会回复其MAC地址。注意在ARP缓存中若已有该IP的MAC地址,则无需广播。
    Linux操作系统下arp协议没有在网络层实现,而是在网络层下面的「邻居子系统」实现的,相当 tcp/ip 网络模型中的「网络接口层」。
    RARP: MAC->IP
    注意不要把ARP和ARQ搞混淆。ARQ 是Automatic repeat request (两个触发条件满足一个即可:定时器倒计时结束还未收到ack包 和 连续收到三个相同的ack包)。

  3. gateway, router, switch和hub
    参考 https://www.xiaolincoding.com/network/1_base/what_happen_url.html

  • 网关gateway 一般是连接两个网络做转换用。

  • 路由器router - 工作在网络层
    路由器和交换机是有区别的。
    因为路由器是基于 IP 设计的,俗称三层网络设备,路由器的各个端口都具有 MAC 地址和 IP 地址;
    而交换机是基于以太网设计的,俗称二层网络设备,交换机的端口不具有 MAC 地址。
    路由器基本原理
    路由器的端口具有 MAC 地址(只接收与自身地址匹配的包,遇到不匹配的包则直接丢弃。),因此它就能够成为以太网的发送方和接收方;同时还具有 IP 地址,从这个意义上来说,它和计算机的网卡是一样的。
    当转发包时,首先路由器端口会接收发给自己的以太网包,然后路由表查询转发目标,再由相应的端口作为发送方将以太网包发送出去。
    在网络包传输的过程中,源 IP 和目标 IP 始终是不会变的,一直变化的是 MAC 地址,因为需要 MAC 地址在以太网内进行两个设备之间的包传输。

  • 交换机switch 工作在MAC层。交换机的设计是将网络包原样转发到目的地。
    注意:计算机的网卡本身具有 MAC 地址,并通过核对收到的包的接收方 MAC 地址判断是不是发给自己的,如果不是发给自己的则丢弃;相对地,交换机的端口不核对接收方 MAC 地址,而是直接接收所有的包并存放到缓冲区中。因此,和网卡不同,交换机的端口不具有 MAC 地址。
    交换机的 MAC 地址表主要包含两个信息:一个是设备的 MAC 地址,另一个是该设备连接在交换机的哪个端口上。
    当 MAC 地址表找不到指定的 MAC 地址会怎么样?这种情况下,交换机无法判断应该把包转发到哪个端口,只能将包转发到除了源端口之外的所有端口上,无论该设备连接在哪个端口上都能收到这个包。这样做不会产生什么问题,因为以太网的设计本来就是将包发送到整个网络的,然后只有相应的接收者才接收包,而其他设备则会忽略这个包。
    此外,如果接收方 MAC 地址是一个广播地址,那么交换机会将包发送到除源端口之外的所有端口。
    以下两个属于广播地址:
    MAC 地址中的 FF:FF:FF:FF:FF:FF
    IP 地址中的 255.255.255.255

  • 集线器hub 工作在物理层。感觉就像一堆金属线的连接而已。收到包后群发到所有端口。

  1. 键入网址到网页显示期间发生了什么?
    https://www.xiaolincoding.com/network/1_base/what_happen_url.html#%E8%AF%BB%E8%80%85%E9%97%AE%E7%AD%94
    ①浏览器解析url
    ②生成一个http请求协议包,把协议包的发送委托给操作系统
    ③操作系统在发送协议包之前先要获取服务器的IP地址。如果在本地的浏览器缓存、操作系统缓存或者hosts文件中存在对应的IP地址,就不需要再访问本地的DNS服务器了。如果不存在,访问本地的DNS服务器,由本地DNS服务器对进行递归访问,即按照层级向下访问,最后得到IP地址。
    ④得到ip地址后。进行TCP连接,三次握手。
    ⑤握手之后,把请求层层封装,通过网卡将数据发送到交换机。交换机会进行校验以及查找交换表转发,到达路由器。路由器把MAC层扒皮,查看目的ip,然后根据路由表选择下一跳,再进行MAC层封装。重复这个过程,最后到达服务器。
    ⑥到达服务器后,会对数据包进行扒皮并且校验。使用FCS校验码校验二进制序列的正确性。在MAC层看目的MAC是不是自己,在网络层看目的ip是不是自己,同时知道上层协议是TCP还是UDP协议。在TCP中知道这是一个什么保文,请求保文、响应报文还是结束连接的报文。通过端口号知道这是交给那么应用进程的。
    ⑦应用进程知道你访问的是什么资源,那么就给客户端返回一个Http响应协议包,把资源封装在其中。通过同样的流程把数据返回给客户端。
    ⑧浏览器拿到数据后,对数据进行渲染,解码,变成了一个页面显示在浏览器上。

  2. 浏览器输入URL后回车,页面没有出现怎么排查问题?
    https://www.xiaolincoding.com/network/1_base/what_happen_url.html#%E8%AF%BB%E8%80%85%E9%97%AE%E7%AD%94
    最直接的办法就是抓包,排查的思路大概有:
    先确定是服务端的问题,还是客户端的问题。先确认浏览器是否可以访问其他网站,如果不可以,说明客户端网络自身的问题,然后检查客户端网络配置(连接wifi正不正常,有没有插网线);如果可以正常其他网页,说明客户端网络是可以正常上网的。
    如果客户端网络没问题,就抓包确认 DNS 是否解析出了 IP 地址,如果没有解析出来,说明域名写错了,如果解析出了 IP 地址,抓包确认有没有和服务端建立三次握手,如果能成功建立三次握手,并且发出了 HTTP 请求,但是就是没有显示页面,可以查看服务端返回的响应码,如果是404错误码,检查输入的url是否正确,如果是500,说明服务器此时有问题,如果是200,F12看看前端代码有问题导致浏览器没有渲染出页面。
    如果客户端网络是正常的,但是访问速度很慢,导致很久才显示出来。这时候要看客户端的网口流量是否太大的了,导致tcp发生丢包之类的问题。
    总之就是一层一层有没有插网线,网络配置是否正确、DNS有没有解析出 IP地址、TCP有没有三次握手、HTTP返回的响应码是什么。

8.关于TCP 3次握手:
https://www.xiaolincoding.com/network/1_base/what_happen_url.html#%E8%AF%BB%E8%80%85%E9%97%AE%E7%AD%94
输入http地址->dns域名解析拿到目标ip地址->tcp初始化syn包,进入syn_sent状态->ip层拼接ip头->arp协议获取路由器的mac地址->拼接mac头->网卡将网络包(syn包)发给路由器。这个过程就是第一个syn包发出去的过程,经过各个路由器转发后,到达了接收方,接收方就开始扒开mac头、ip头,然后送到tcp层,tcp协议栈检查tcp头是一个syn包,于是就进入syn_recv状态,然后回复syn、ack报文给对方。
注意:客户端发送给服务端的第一个网络包是tcp三次握手中第一个syn报文,也是要经过ip层,数据链路层,交换机,路由器。

  1. 关于网卡收包和发包的过程
    下面这个连接不错
    https://www.junmajinlong.com/coding/tcp_socket/

  2. 关于5种IO模型
    https://www.junmajinlong.com/coding/IO_Model/

  3. websocket如何进行限流?
    https://www.xiaolincoding.com/network/2_http/http_websocket.html#%E6%80%BB%E7%BB%93
    连接限制:通过限制连接数来控制服务器资源的使用情况。可以设置一个最大连接数,当连接数超过这个限制时,新的连接请求就会被拒绝。这种方法通常需要使用一些负载均衡器来实现。
    速率限制:通过限制每个客户端的请求速率来控制服务器的负载。可以设置一个固定的速率,每个客户端只能在一定时间内发送一定数量的请求。这种方法通常需要使用一些中间件来实现,例如 Redis 等。
    消息大小限制:通过限制每个消息的大小来控制服务器的负载。可以设置一个最大的消息大小,当消息大小超过这个限制时,消息就会被拒绝。这种方法通常需要在 WebSocket 协议的底层实现中进行处理。

  4. 关于TCP3次握手, 4次挥手
    a. 客户端 connect 成功返回是在第二次握手,服务端 accept 成功返回是在三次握手成功之后。
    b. TCP 3次握手优化:
    https://www.xiaolincoding.com/network/3_tcp/tcp_optimize.html#%E5%B0%8F%E7%BB%93
    b.1 客户端的优化
    当客户端发起 SYN 包时,可以通过 tcp_syn_retries 控制其重传的次数。
    b.2 服务端的优化
    当服务端 SYN 半连接队列溢出后,会导致后续连接被丢弃,可以通过 netstat -s 观察半连接队列溢出的情况,如果 SYN 半连接队列溢出情况比较严重,可以通过 tcp_max_syn_backlog、somaxconn、backlog 参数来调整 SYN 半连接队列的大小。
    服务端回复 SYN+ACK 的重传次数由 tcp_synack_retries 参数控制。如果遭受 SYN 攻击,应把 tcp_syncookies 参数设置为 1,表示仅在 SYN 队列满后开启 syncookie 功能,可以保证正常的连接成功建立。
    服务端收到客户端返回的 ACK,会把连接移入 accpet 队列,等待进行调用 accpet() 函数取出连接。
    可以通过 ss -lnt 查看服务端进程的 accept 队列长度,如果 accept 队列溢出,系统默认丢弃 ACK,如果可以把 tcp_abort_on_overflow 设置为 1 ,表示用 RST 通知客户端连接建立失败。
    如果 accpet 队列溢出严重,可以通过 listen 函数的 backlog 参数和 somaxconn 系统参数提高队列大小,accept 队列长度取决于 min(backlog, somaxconn)。
    b.3 绕过三次握手
    TCP Fast Open 功能可以绕过三次握手,使得 HTTP 请求减少了 1 个 RTT 的时间,Linux 下可以通过 tcp_fastopen 开启该功能,同时必须保证服务端和客户端同时支持。
    c. 当被动关闭方在 TCP 挥手过程中,「没有数据要发送」并且「开启了 TCP 延迟确认机制(默认会开启)」,那么第二和第三次挥手就会合并传输,这样就出现了三次挥手。
    当被动关闭方在 TCP 挥手过程中,「没有数据要发送」,同时「关闭了 TCP 延迟确认机制」,那么就会是四次挥手。

close()、shutdown()函数
https://www.junmajinlong.com/coding/tcp_socket/
通用的close()函数可以关闭一个文件描述符,当然也包括面向连接的网络套接字描述符。当调用close()时,将会尝试发送send buffer中的所有数据。但是close()函数只是将这个套接字引用计数减1,就像rm一样,删除一个文件时只是移除一个硬链接数,只有这个套接字的所有引用计数都被删除,套接字描述符才会真的被关闭,才会开始后续的四次挥手中。对于父子进程共享套接字的并发服务程序,调用close()关闭子进程的套接字并不会真的关闭套接字,因为父进程的套接字还处于打开状态,如果父进程一直不调用close()函数,那么这个套接字将一直处于打开状态,将一直进入不了四次挥手过程。

而shutdown()函数专门用于关闭网络套接字的连接,和close()对引用计数减一不同的是,它直接掐断套接字的所有连接,从而引发四次挥手的过程。可以指定3种关闭方式:
a.关闭写。此时将无法向send buffer中再写数据,send buffer中已有的数据会一直发送直到完毕。
b.关闭读。此时将无法从recv buffer中再读数据,recv buffer中已有的数据只能被丢弃。
c.关闭读和写。此时无法读、无法写,send buffer中已有的数据会发送直到完毕,但recv buffer中已有的数据将被丢弃。
无论是shutdown()还是close(),每次调用它们,在真正进入四次挥手的过程中,它们都会发送一个FIN。

  1. 关于链路层重传和TCP重传的区别
    下面这个链接讲的很好。
    https://www.wangan.com/p/11v6c8a1f30ffaa8
    我个人的理解:
    a. 链路层重传是节点到节点的,比如说终端到网关,路由器到路由器,等等。TCP重传是端到端的,也就是从发送方到接收方。
    b. 光链路层重传是不够的,因为节点里面发生了什么链路层不知道,比如说某个路由器的buffer overflow,包被丢掉了,而链路层只知道自己把包送到了,上层发生了什么不知道。
    c. 光TCP重传也是不够的,因为TCP重传太慢了,本来可能某两个路由器之间重传一下就够了,现在要从发送方再重新发一遍,巨慢(等ACK 超时-超时重传, 收到3次重复ACK-快速重传,等等)。

  2. 关于TCP的滑动窗口
    https://www.xiaolincoding.com/network/3_tcp/tcp_feature.html#%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3
    TCP 头里有一个字段叫 Window,也就是窗口大小。
    这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。 所以,通常窗口的大小是由接收方的窗口大小来决定的
    发送方发送的数据大小不能超过接收方的窗口大小,否则接收方就无法正常接收到数据。

注意:
a. 滑动窗口是针对flow control, 不是congestion control!

  1. 关于TCP的三个窗口swnd, rwnd, cwnd
    https://www.xiaolincoding.com/network/3_tcp/tcp_feature.html#%E6%8B%A5%E5%A1%9E%E6%8E%A7%E5%88%B6
    拥塞窗口 cwnd是发送方维护的一个的状态变量,它会根据网络的拥塞程度动态变化的。
    发送窗口 swnd 和接收窗口 rwnd 是约等于的关系,那么由于加入了拥塞窗口的概念后,此时发送窗口的值是swnd = min(cwnd, rwnd),也就是拥塞窗口和接收窗口中的最小值。

  2. 关于syn_rcvd(半连接)队列和accepted(全连接)队列。
    a. backlog是指accepted队列的长度。
    https://www.xiaolincoding.com/network/3_tcp/tcp_optimize.html#%E6%9C%8D%E5%8A%A1%E7%AB%AF%E4%BC%98%E5%8C%96
    严格的说,accept 队列的长度取决于 somaxconn 和 backlog 之间的最小值,也就是 min(somaxconn, backlog),其中:
    somaxconn 是 Linux 内核的参数,默认值是 128,可以通过 net.core.somaxconn 来设置其值;
    backlog 是 listen(int sockfd, int backlog) 函数中的 backlog 大小;

  3. 调用 close 函数和 shutdown 函数有什么区别?
    https://www.xiaolincoding.com/network/3_tcp/tcp_optimize.html#%E4%B8%BB%E5%8A%A8%E6%96%B9%E7%9A%84%E4%BC%98%E5%8C%96
    调用了 close 函数意味着完全断开连接,完全断开不仅指无法传输数据,而且也不能发送数据。 此时,调用了 close 函数的一方的连接叫做「孤儿连接」,如果你用 netstat -p 命令,会发现连接对应的进程名为空。
    使用 close 函数关闭连接是不优雅的。于是,就出现了一种优雅关闭连接的 shutdown 函数,它可以控制只关闭一个方向的连接。

  4. 注意进程崩溃和主机宕机的区别。
    我的理解是进程崩溃的时候,操作系统在回收进程资源的时候会调用close(), 会导致发送FIN报文。
    而主机宕机的时候,操作系统无法感知,所以不会调用close(),也就没有FIN报文。所以对方需要TCP 保活机制来探测这边是不是发生了主机宕机。

  5. HTTP 的 Keep-Alive 和TCP的 Keep-Alive区别?
    https://www.xiaolincoding.com/network/3_tcp/tcp_http_keepalive.html#tcp-%E7%9A%84-keepalive
    HTTP 的 Keep-Alive 也叫 HTTP 长连接,该功能是由「应用程序」实现的,可以使得用同一个 TCP 连接来发送和接收多个 HTTP 请求/应答,减少了 HTTP 短连接带来的多次 TCP 连接建立和释放的开销。
    TCP 的 Keepalive 也叫 TCP 保活机制,该功能是由「内核」实现的,当客户端和服务端长达一定时间没有进行数据交互时,内核为了确保该连接是否还有效,就会发送探测报文,来检测对方是否还在线,然后来决定是否要关闭该连接。

  6. 从内核角度看TCP三次握手。
    下面这个链接讲的非常好。下面的内容都是引用的这个链接。
    https://juejin.cn/post/7162499365871812644
    a. listen的主要作用就是申请和初始化接收队列(包括全连接队列和半连接队列)
    listen()函数没有阻塞,accept()函数才有阻塞。
    b. 半连接队列的数据结构是hash table,全连接队列的数据结构是queue。
    c. 简述一下从内核看TCP三次握手过程
    server端调用listen创建好连接队列 (【半连接队列】和【全连接队列】),并监听指定的端口

client选出一个可用端口,修改自己的socket状态为TCP_SYN_SENT,并向server发起syn连接,并启动一个【重传定时器】

server端收到syn包后,检查【半连接队列】和【全连接队列】是否满了
如果满了就丢掉这个握手包(一定时间后client端在第一次握手时建立的重传定时器会重新发送SYN包给server)
如果没有满则继续向下

server端创建一个request_sock对象,并且修改该sock对象的状态为SYN RCV,并放入【半连接队列】,然后创建一个SYN ACK响应包发送给client端,然后启动一个【重传定时器】
client 收到SYN ACK包,删除第一次握手时创建的【重传定时器】,修改自己的状态为 ESTABLISHED(表示client连接建立完成),打开【TCP保活计时器】,并向server回复一个【ACK包】。

server端收到ACK包后
如果【全连接队列】没有满,则删除第二次握手创建的 【重传定时器】,将该client对应的在【半连接队列】里的sock对象删除,创建一个新的socket对象放入到【全连接队列】,将server端的socket状态修改为 ESTABLISHED(表示server端与该client连接建立完成)
如果全连接队列满了,则会丢弃client发来的ack包。然后server端在第二次握手时创建的【重传定时器】在一定时间后会向client重新传递【SYN ACK】包,client再次响应ACK包

  1. 关于ARP, RARP 和 DHCP
    https://www.xiaolincoding.com/network/4_ip/ip_base.html#arp
    ARP: ARP 协议是已知 IP 地址求 MAC 地址。
    RARP: RARP 协议正好相反,是已知 MAC 地址求 IP 地址。例如将打印机服务器等小型嵌入式设备接入到网络时就经常会用得到。
    通常这需要架设一台 RARP 服务器,在这个服务器上注册设备的 MAC 地址及其 IP 地址。然后再将这个设备接入到网络,接着该设备会发送一条「我的 MAC 地址是XXXX,请告诉我,我的IP地址应该是什么」的请求信息。
    RARP 服务器接到这个消息后返回「MAC地址为 XXXX 的设备,IP地址为 XXXX」的信息给这个设备。
    最后,设备就根据从 RARP 服务器所收到的应答信息设置自己的 IP 地址。

RARP和DHCP啥区别?
DHCP作用是用来分配IP。 与其功能相同的协议是RARP。 两者区别是:DHCP同一个IP可以分配给不同的主机(不同时在线);RARP只能将同一个IP分配给同一台主机。
DHCP协议是基于UDP包。

  1. ICMP和IGMP啥区别?
    https://www.xiaolincoding.com/network/4_ip/ip_base.html#igmp
    ICMP 全称是 Internet Control Message Protocol,也就是互联网控制报文协议。
    a)ICMP的包整个就放在IP包的payload里面。注意ICMP是网络层协议,没有端口号!
    b)针对TCP协议,如果端口不可达,是回复 RST 报文
    针对 UDP协议,如果端口不可达,是回复 ICMP 报文
    c) traceroute uses UDP on incrementing ports for every hop. If a hop is unreachable, it will send ICMP packet to the source.

IGMP 是因特网组管理协议,工作在主机(组播成员)和最后一跳路由之间,如上图中的蓝色部分。
IGMP 报文向路由器申请加入和退出组播组,默认情况下路由器是不会转发组播包到连接中的主机,除非主机通过 IGMP 加入到组播组,主机申请加入到组播组时,路由器就会记录 IGMP 路由器表,路由器后续就会转发组播包到对应的主机了。
IGMP 报文采用 IP 封装,IP 头部的协议号为 2,而且 TTL 字段值通常为 1,因为 IGMP 是工作在主机与连接的路由器之间。

Acronyms:
ARP:
CIDR:
DHCP:
ICMP:
IGMP:
MSL: maximum ?
MSS:
MTU:
PAWS: Protection Against Wrapped Sequences 防止(时间戳)回绕
RARP:
skb:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值