Network Socket 套接字

在建立 Socket 的时候,应该设置什么参数呢?Socket 编程进行的是端到端的通信,往往意识不到中间经过多少局域网,多少路由器,因而能够设置的参数,也只能是端到端协议之上网络层和传输层的。

在网络层,Socket 函数需要指定到底是 IPv4 还是 IPv6,分别对应设置为 AF_INET 和 AF_INET6。

另外,还要指定到底是 TCP 还是 UDP。还记得咱们前面讲过的,TCP 协议是基于数据流的,所以设置为 SOCK_STREAM,而 UDP 是基于数据报的,因而设置为 SOCK_DGRAM。

基于tcp socket 函数调用过程

  1. 服务器调用bind 函数开启一个端口进行监听,当一个网络包来的时候,内核要通过 TCP 头里面的这个端口,来找到你这个应用程序,把包给你。为什么要 IP 地址呢?有时候,一台机器会有多个网卡,也就会有多个 IP 地址,你可以选择监听所有的网卡,也可以选择监听一个网卡,这样,只有发给这个网卡的包,才会给你。
  2. 当服务端有了 IP 和端口号,就可以调用 listen 函数进行监听。在 TCP 的状态图里面,有一个 listen 状态,当调用这个函数之后,服务端就进入了这个状态,这个时候客户端就可以发起连接了。在内核中,为每个 Socket 维护两个队列。一个是已经建立了连接的队列,这时候连接三次握
  3. 在内核中,为每个 Socket 维护两个队列。一个是已经建立了连接的队列,这时候连接三次握手已经完毕,处于 established 状态;一个是还没有完全建立连接的队列,这个时候三次握手还没完成,处于 syn_rcvd 的状态。
  4. 接下来,服务端调用 accept 函数,拿出一个已经完成的连接进行处理。如果还没有完成,就要等着。
  5. 在服务端等待的时候,客户端可以通过 connect 函数发起连接。先在参数中指明要连接的 IP 地址和端口号,然后开始发起三次握手。内核会给客户端分配一个临时的端口。一旦握手成功,服务端的 accept 就会返回另一个 Socket
    • 这是一个经常考的知识点,就是监听的 Socket 和真正用来传数据的 Socket 是两个,一个叫作监听 Socket,一个叫作已连接 Socket。
  6. 连接建立成功之后,双方开始通过 read 和 write 函数来读写数据,就像往一个文件流里面写东西一样。

基于 udp socket 函数调用过程

对于 UDP 来讲,过程有些不一样。UDP 是没有连接的,所以不需要三次握手,也就不需要调用 listen 和 connect,但是,UDP 的交互仍然需要 IP 和端口号,因而也需要 bind。UDP 是没有维护连接状态的,因而不需要每对连接建立一组 Socket,而是只要有一个 Socket,就能够和多个客户端通信。也正是因为没有连接状态,每次通信的时候,都调用 sendto 和 recvfrom,都可以传入 IP 地址和端口。

Network 路由网关与协议

  • 根据路由规则转发数据包的三层设备
    • 转发网关(不修改源IP 和目的MAC 地址)
    • NAT 网关 (修改源IP 和目的MAC 地址)
  • 路由策略与策略路由
    • 除了可以根据目的 ip 地址配置路由外,还可以根据多个参数来配置路由,这就称为策略路由。
    • 一条路由规则中可以包括多条路径例如:
      • ip route add default scope global nexthop via 100.100.100.1 weight 1 nexthop via 200.200.200.1 weight 2
  • 一条路由规则至少包括以下3个信息
    • 目的网络:这个包想去哪儿?
    • 出口设备:将包从哪个口扔出去?
    • 下一跳网关:下一个路由器的地址。
    • 核心思想是根据目的IP 来配置路由
  • 路由协议要在路由器之间交换信息,这些信息的交换还需要走路由吗?不是死锁了吗?
  • 路由器之间信息的交换使用什么协议呢?报文格式是什么样呢?

Network ICMP 协议与Ping 、 Traceroute

  1. icmp 分为 查询报文与有差错控制报文
  2. ping 使用查询报文,traceroute 使用差错报文
  3. 查询报文有 ICMP ECHO REQUEST 与 ICMP ECHO REPLY,查询的类型为8,应答的报文为0
  4. 差错报文:
    • 终点不可达
      • 网络不可达 (没找到地方)
      • 主机不可达 (找到地方没找到人)
      • 协议不可达 (找到地方,找到人,语言不通)
      • 端口不可达 (找到地方,找到人,要说的事情对不上)
      • 分片错误 (因为过程中策略限制,无法送达)
    • 源站抑制 (告诉发送方减小发送的数量)
    • 时间超时 (超过网络包的生存时间)
    • 路由重定向(告诉发送方下次走另外一条路线)

Traceroute 的第一个作用就是故意设置特殊的 TTL,来追踪去往目的地时沿途经过的路由器。Traceroute 的参数指向某个目的 IP 地址,它会发送一个 UDP 的数据包。将 TTL 设置成 1,也就是说一旦遇到一个路由器或者一个关卡,就表示它“牺牲”了。如果中间的路由器不止一个,当然碰到第一个就“牺牲”。于是,返回一个 ICMP 包,也就是网络差错包,类型是时间超时

Traceroute 还有一个作用是故意设置不分片,从而确定路径的 MTU。要做的工作首先是发送分组,并设置“不分片”标志。发送的第一个分组的长度正好与出口 MTU 相等。

报文类型类型代码描述
目的不可达3当数据包无法到达目的地时发送,例如网络不可达、主机不可达、协议不可达、端口不可达等
超时11当数据包的 TTL(生存时间)字段降为 0 时发送,或分片重组超时
参数问题12当 IP 数据包中的参数有问题时发送,例如 IP 头部中的某些字段值无效
重定向5当路由器发现一个更有效的路由时发送,建议发送方使用更短的路径
回显请求8用于测试目的主机的可达性和响应时间,发送方发送回显请求
回显应答0对回显请求的响应,确认目的主机的可达性
时间戳请求13用于请求目的主机的时间戳信息,以便同步网络设备的时钟
时间戳应答14对时间戳请求的响应,包含目的主机的时间戳信息
信息请求15请求目的主机的特定信息
信息应答16对信息请求的响应
路由器通告(IPv6)9用于 IPv6,由路由器发送给邻近节点,提供网络配置信息
路由器请求(IPv6)10用于 IPv6,由节点发送给路由器,请求网络配置信息
邻居通告(IPv6)135用于 IPv6,通告节点的可达性
邻居请求(IPv6)133用于 IPv6,请求邻居节点的信息
重定向消息(IPv6)134用于 IPv6,类似于 IPv4 的重定向报文,但用于 IPv6 环境

Network 链路层主要解决什么问题

hub 集线器存在的问题

  1. 这个包是发给谁的?谁应该接收? ( mac 地址解决)
  2. 大家都在发,会不会产生混乱? (轮流协议)
  3. 有没有谁先发、谁后发的规则?如果发送的时候出现了错误,怎么办?(随机访问控制接入协议)
  • Arp 协议
  • 已知IP 未知MAC 通过广播请求对方的MAC 地址
  • Aarp
  • 已知 MAC 未知 IP

交换机

记录目标PC MAC 地址和转发的端口 形成对应 MAC 地址表,通过学习不再通过广播来发送和接收。交换机通过学习生成转发表(MAC 地址表);有过期的时间。

如果一个局域网里面有多个交换机,ARP 广播的模式会出现什么问题呢?

如果是通过级联方式组网,A会将广播转发给B,B会广播到所有的端口。如果存在环路,会形成广播风暴。

Network DHCP 与 PXE

dhcp 的工作方式

  1. c -> dhcp discover
  2. s -> dhcp offer
  3. c -> dhcp request
  4. s -> dhcp ack

1、dhcp Discover (只有MAC 地址)

2、dhcp Offer

3、dhcp Request

4、dhcp Ack

PXE 协议

dhcp 服务器配置中的PXE 参数

ddns-update-style interim;
ignore client-updates;
allow booting;
allow bootp;
subnet 192.168.1.0 netmask 255.255.255.0
{
option routers 192.168.1.1;
option subnet-mask 255.255.255.0;
option time-offset -18000;
default-lease-time 21600;
max-lease-time 43200;
range dynamic-bootp 192.168.1.240 192.168.1.250;
filename “pxelinux.0”;
next-server 192.168.1.180;

}