概念:
没有网络,数据只能单主机多进程多线程交互数据,当业务复杂,必须要将多台主机数据交互,多台计算机连接在一起,完成数据共享就称为网络互联 ,一个小实验室的内部主机连接,就形成了一个局域网,多个局域网可以通过路由器交互数据,而广域网是局域网的相对概念,针对主机数目而定,广域网可以将相隔千里之外的计算机连接
网络支持长距离主机通信,负责主机之间交互数据,而数据具有自己的属性和内容,为了区分数据的含义,需要主机提前约定,称为软件协议,一般是程序员提前编写好的代码,而数据在计算机就是01序列,如何用硬件表示01序列,例如是高电平,低电平还是根据频率区分需要硬件上的标准,因此我们认为网络是具有硬件标准,软件协议的,而协议就是软件所维护的一种约定
1. OS内存在多种协议约定,协议具体实现就是以结构体对象的方式发给对方,(报头)
2. 协议是一种软件,而软件是可以分层的,类似于操作系统为了管理文件定义struct file的结构体与每个文件具体实现划分开
3. 协议在设计的时候,被层状划分的好处是,解决复杂场景,进行功能解耦,便于维护,例如两个人在打电话,人关注的是业务问题,电话专注的是编码解码问题,相当于人和手机只需要专注于自己要处理的问题,下一次换成外国人打电话同样可以实现想要的功能,这就是便于维护
网络在设计协议分层的时候,将协议划分成了自顶向下为应用层,传输层,网络层,数据链路层,物理层,每一层协议栈专注于自己要解决的问题,
从通信范畴看:传输层 解决丢包问题,(长距离传输对方未收到)——>在操作系统内部实现
网络层 解决定位问题(找到目标主机)——>在操作系统内部实现
数据链路层,物理层(A,B经过路由器转发找到下一跳主机)——>网卡驱动/网卡实现
从用户范畴看:应用层专注于数据处理问题,通过传输层提供的系统调用设计的上层应用
除了物理层我们将上四层称为TCP/IP协议,TCP是传输层最重要的协议,IP是网络层最重要的协议,他们都在操作系统内实现,是最重要的通信范畴,因此整个协议以此命名
未来的计算机网络要学习的协议就是关注于上层应用怎么写,操作系统怎么做,用传输层提供的系统调用,完成网络通信
OSI七层模型与TCP/IP协议
OSI(Open System Interconnection,开放系统互连)七层网络模型称为开放式系统互联参考模型, 是一个逻辑上的定义和规范;
把网络从逻辑上分为了7层. 每一层都有相关、相对应的物理设备,比如路由器,交换机;
OSI 七层模型是一种框架性的设计方法,其最主要的功能使就是帮助不同类型的主机实现数据传输;
它的最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整. 通过七 个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯;
我们按照TCP/IP四层模型学习,这是蓝图与具体实现的差别
TCP/IP五层(或四层)模型
1. TCP/IP是一组协议的代名词,它还包括许多协议,组成了TCP/IP协议簇. 2. TCP/IP通讯协议采用了5层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求.
3. 物理层: 负责光/电信号的传递方式. 比如现在以太网通用的网线(双绞 线)、早期以太网采用的的同轴电缆 (现在主要用于有线电视)、光纤, 现在的wifi无线网使用电磁波等都属于物理层的概念。物理层的能力决 定了最大传输速率、传输距离、抗干扰性等. 集线器(Hub)工作在物理层.
3. 数据链路层: 负责设备之间的数据帧的传送和识别. 例如网卡设备的驱动、帧同步(就是说从网线上检测 到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作. 有以太 网、令牌环网, 无线LAN等标准. 交换机(Switch)工作在数据链路层. (局域网工作在数据链路层)
4. 网络层: 负责地址管理和路由选择. 例如在IP协议中, 通过IP地址来标识一台主机, 并通过路由表的方式规 划出两台主机之间的数据传输的线路(路由). 路由器(Router)工作在网路层.(目的IP地址对目标主机做定位)
以上三层构建路上相关设备能保证数据由A——>B 5. 传输层: 负责两台主机之间的数据传输. 如传输控制协议 (TCP), 能够确保数据可靠的从源主机发送到目标 主机,可靠性由发送数据的主机自己负责
网络层和传输层在os内实现
6. 应用层: 负责应用程序间沟通,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问 协议(Telnet)等. 我们的网络编程主要就是针对应用层 (数据分析)
用户层实现
综上:一台主机他在操作系统内核实现了从传输层到网络层,路由器实现了从网络层到物理层,交换机实现了从网络层到物理层,集线器只实现了物理层
局域网中两台主机通信过程
局域网中表示主机的唯一性:MAC地址
网卡地址IP:(查看命令:ifconfig)
inet:内网IP地址
同一局域网我们认为两台主机在逻辑上直接通信,在物理上我们认为,数据不能直接从应用层到对方应用层,每一层都有自己协议定制方案,有自己的协议报头,从上往下添加报头(封装),从下往上要去掉报头,收到报文,将抱头和有效载荷分离(解包)
当上层把数据交给下层,下层有自己的协议,下层把上层交付的数据,结合这一层的协议,给他添加一层报头,供未来对方的同层协议解包,数据提取,同层协议收到这个数据之后,解除报头,向上递交数据
抱头是发送方和接收方相互传递属性字段,同层协议会提前约定好一些共识字段,收到数据可以对数据解析
局域网通信实例,手机投屏电视,二者认为在一个局域网下通信
用户产生数据:你好,信息向下交付,逐层添加报头,最后在局域网中跑的是数据帧
局域网中每台主机都会分析其他主机发来的报文,如果MAC地址与自己吻合就会分析报文,否则丢弃
数据的封装
数据包封装和分用 不同的协议层对数据包有不同的称谓,在传输层叫做段(segment),在网络层叫做数据报 (datagram),在链 路层叫做帧(frame). 应用层数据通过协议栈发到网络上时,每层协议都要加上一个数据首部(header),称为封装 (Encapsulation). 首部信息中包含了一些类似于首部有多长, 载荷(payload)有多长, 上层协议是什么等信息. 数据封装成帧后发到传输介质上,到达目的主机后每层协议再剥掉相应的首部, 根据首部中的 "上层协议 字段" 将数据交给对应的上层协议处理.
不同局域网主机通信过程
两个局域网通过路由器连接,路由器可以根据IP地址,封装MAC数据帧,解决下一跳问题,因此数据交付的过程中,MAC帧一直变化,而目的IP是不变的,路由器跨网络传送,因此至少两个网络接口,级联两个网络
IP地址在特定网段(公网)表识主机的唯一性
网络中的地址管理
认识IP地址
IP协议有两个版本, IPv4和IPv6. 凡是提到IP协议, 没有特殊说明的, 默认都是指IPv4 IP地址是在IP协议中, 用来标识网络中不同主机的地址; 对于IPv4来说, IP地址是一个4字节, 32位的整数; 我们通常也使用 "点分十进制" 的字符串表示IP地址, 例如 192.168.0.1 ; 用点分割的每一个数字表示一个 字节, 范围是 0 - 255;
认识MAC地址
MAC地址用来识别数据链路层中相连的节点; 长度为48位, 及6个字节. 一般用16进制数字加上冒号的形式来表示(例如: 08:00:27:03:fb:19) 在网卡出厂时就确定了, 不能修改. mac地址通常是唯一的(虚拟机中的mac地址不是真实的mac地址, 可 能会冲突; 也有些网卡支持用户配置mac地址
网络套接字
两个主机可以在公网内以唯一的方式表示对方(IP),但是把数据交到对方主机并不是目的,数据必须交付给对方客户端,并且是启动的客户端(服务器),因此必须是主机上指定的一个进程,因此网络通信的本质是进程间通信,而端口号可以表示主机上唯一的进程,端口号告诉操作系统要把数据交给哪个进程,TCP(UDP传输层协议)根据发来的端口号决定交给哪个进程,端口号不能和多进程绑定,但是一个进程可以绑定多个端口号
端口号
端口号(port)是传输层协议的内容. 端口号是一个2字节16位的整数; 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理; IP地址 + 端口号能够标识网络上的某一台主机的某一个进程; 一个端口号只能被一个进程占用
(IP+PORT)表示唯一进程,称为套接字
套接字编程实现网络上的进程间通信
传输层协议种类:TCP/UDP
认识TCP协议 有连接 可靠传输 面向字节流
认识UDP协议 无连接 不可靠传输 面向数据报
网络字节序
我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏 移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢? 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出; 接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存; 因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址. TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节. 不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据; 如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即 可
为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络 字节序和主机字节序的转换。
常见套接字:
域间socket,用网络通信的接口实现本地进程间通信
,原始socket 允许你绕过网络层,使用其他层的接口,访问更加底层的协议,编写工具
,网络socket 在网络中实现进程间通信
三种套接字类型不一样,Linux为了屏蔽接口使用的差异化进行了统一处理
socket编程接口
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address,
socklen_t address_len);
// 开始监听socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address,
socklen_t* address_len);
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
sockaddr结构
socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,以及后面的UNIX Domain Socket. 然而, 各种网络协议的地址格式并不相同
Pv4和IPv6的地址格式定义在netinet/in.h中,IPv4地址用sockaddr_in结构体表示,包括16位地址类型, 16 位端口号和32位IP地址. IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6. 这样,只要取得某种sockaddr结构体的首地址, 不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容. socket API可以都用struct sockaddr *类型表示, 在使用的时候需要强制转化成sockaddr_in; 这样的好 处是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构体指针做为 参数;