很高兴你已经完成了 apue 的基础部分(Linux 环境编程学习笔记),如果你对这部分知识不甚了解,建议你先完成它。在 Linux 环境编程中,已经对基本的 socket 编程做了一个简单的介绍,如果你还没读那部分内容,建议你非常有必要再去看一遍,因为博客并不打算重复那基础知识。

为了能够顺利进入 unp,先回顾下计算网络的大体架构。

1. 计算机网络

1.1 协议概述

这里默认你已经知道了什么是 ISO/OSI 七层模型,如果你一点网络基础也没有,这个系列博客对你来说应该是有相当的难度的。另一方面,希望你知道“协议”是什么意思。如果换成 C 语言来描述,协议就是某个 struct 结构体,有很多函数可以对结构体(协议)进行解读。

底层的协议,可以为其上层协议服务,是指底层的结构体中的数据域,就是上层的某个结构体的对象。


1-网络协议基础_socket


图1 从网络数据中抓取的很多数据包


图 1 中,是使用软件 OmniPeek 抓取的数据包(下一篇文章我会介绍这些工具,给你下载地址,所以这一篇,看看就行,不要着急去下载),这些数据包都是二层数据链路层上或取的,它们就是“帧”。图中只查看了第 22 号帧结构,你可以把帧理解成一个 struct frame 结构:

struct frame {
char destination[6]; // 目标网卡地址
char source[6]; // 源网卡地址
short protocol; // 承载的协议,即 data 域是个什么协议,在图 1 中是 ip 协议
char *data; // 数据域

仔细看图 1,你隐约可以看到二进制数据里包含了 hello world 的字样^_^

从图 1 中我们还可以看到,struct frame 承载了 ip 协议,而 ip 协议又承载了 tcp 协议,tcp 协议又承载了 ftp 协议。这看起来就像:

struct frame {
//...
struct ip *data;
}

struct ip {
//...
struct tcp *data;
}

struct tcp {
//...

实际上在网络编程中,我们的重心基本在 ip 层之上,即我们比较关心传输层的协议,传输层包含两个非常重要的协议就是 tcp 和 udp 协议。在后面的学习中,将会用大量篇幅围绕这这两个协议进行学习。

作为一名开发人员来说,确实不需要怎么关心二三层怎么工作的,但是了解一下对你也没有坏处,技多不压身嘛。如果有必要的话,关于三层的 ip 层协议,我们还是会详细的去学习。

1.2 不同层的工作内容

在实际的 tcp/ip 协议簇中,一般分成网络接口层(LLC、MAC),ip 层,传输层和应用层。我比较倾向于把网络接口层对应到二层,而一层一般是物理层。ip 层对应到三层协议,传输层对应到四层协议,应用层对应到五、六、七层。

  • 二层网络接口层

有时可以直接说数据链路层,简称链路层,这一层传输的数据是“帧”结构,不同的网络传输的帧结构也不大一样,在我们经常用的以太网中,用的是 2 型以太网帧。它的结构这里就不细讲了。

二层最主要的功能就是把帧送到目标网卡上。

一般在二层,都是使用二层交换机这个设备来进行转发的,换句话说,交换机这个设备只认识“帧”这个东东,它可以把网线上的 2 进制数据中的帧给提取出来。因此可以说,交换机具备一定的“智能”,它认识这种“帧”结构的数据,但是它肯定是不认识 ip 数据包,tcp 数据包……

在二层,交换机是根据帧中包含的 MAC 地址将数据送到目标机器的。因为交换机的内存里保存了一张 MAC 地址表,它记录了(MAC 地址 -> 交换机接口)的映射关系。

  • 三层 ip 层

这一层传输的数据叫 packet,中文叫数据包,或者叫数据报。这一层最主要的目的就是根据 ip 地址把数据报发送到对应的网络。也就是说三层最主要的功能就是路由,主要有路由器这个设备来完成这个工作。路由器,它只认识 ip 数据报,它可以根据 ip 数据报中的 ip 地址把 ip 数据包从某个端口转发出去。

当然除了路由之外,三层也有拥塞控制啊等等功能。

  • 四层传输层

这一层传输的数据叫 segment,中文叫数据段,所以你会经常听到什么 fin 段,syn 段,ack 段什么的。

这一层最主要的功能就是根据端口号把数据段送到目标进程。当然了,四层的功能远远不止是这个,特别是对于 tcp 来说,它简直是太复杂了。后面我们肯定是要抓取网络数据帧进行分析了。

以上只是针对网络编程来说我们需要简单了解的东西,当然如果你是想学习网络工程师什么的,不建议你再继续往下读了,你应该去学习思科或华为的网络工程师认证。

2. 网络编程

在掌握了基本的计算机网络原理,以及深入理解传输层的协议后,就可以着手 socket 网络编程啦,只有这样,才能学的更加深入,才能分析各种网络异常,才能好好的调试网络程序的 bug 是不是?

在实际工作中,对于网络编程的一般情况来说,是比较容易的。但网络编程的难点在哪里呢?在于各种异常情况的处理:

  • 纳尼?收不到数据包?
  • 咦,tcp 连接怎么断了?
  • 卧槽,我这里明明看到你还在线啊?!!!
  • 尼玛,怎么数据收少了啊!
  • ……

3. 总结

  • 可能讲了一堆废话你不愿意看
  • 还是简单了解一下二三四层主要的工作内容吧