目录
前言
本文是计算机网络系列的第一篇文章,将会从基础的开始,本文主要来介绍一些,计算机网络的一些基础常识,以便后续的学习和理解;
1. 网络的发展
简单了解一下:
在计算机起初发展时,计算机之间是相互独立的;多台计算机想要配合工作,需要把数据拷贝到磁盘,然后再拿到其他计算机是读取;这样的执行效率太低;
为了便于多台计算机之间互相配合工作,将多台机器连接在一起,把执行的数据上传到公共服务器当中,其他计算机可以随时存取;
随着计算机数量的增多,基本的几台机器互联并不能满足需求,比如两个研究机构之间先要进行科研交流,这时就需要把双方的数据通过网络进行通信,此时就需要用到路由器来完成;这也就是局域网的雏形;
随着计算机的普及,计算机之间的通信范围更广,各地区之间的计算机要实现通信,就需要通过网络连接,通过交换器和路由器实现计算机之间的通信;
2. 网络通信
网络通信其实就是两台计算机之间进行通信;
两台计算机通过网络进行数据的传输;
计算机内部的硬件设备也需要通信,各个硬件之间需要数据传输;和网络通信不同的是,通信的距离不同;比如:从磁盘将数据拷贝到内存,磁盘到内存进行数据传输,网络通信也就是两台计算机之间网卡的数据传输,区别就是距离变远了;
网络通信数据传输的距离变长了,数据传输时就会存在一系列问题:
- 数据传输过程中,丢包了怎么办?
- 目标机器定位的问题
- 如何将数据经过多个设备之后,还能准确的把数据推送到远端机器
为了解决这些问题,于是定制了各种协议,什么是协议? " 协议 ”本质就是一种约定;
计算机之间的传输媒介是光信号和电信号,通过"频率"和"强弱”来表示 0和 1 这样的信息,要想传递各种不同的信息,就需要约定好双方的数据格式;比如:如果一方以信号强弱表示0、1,一方以信号频率表示0、1;这样怎么正确的接收数据,所以定制协议是非常有必要的;
计算机生产厂商有很多;计算机操作系统,也有很多;计算机网络硬件设备,还是有很多;如何让这些不同厂商之间生产的计算机能够相互顺畅的通信?就需要约定一个共同的标准,大家都来遵守,这就是 网络协议;网络通信中就存在着各种各样的协议,定制协议就要编码实现协议;
逻辑上,我们认为计算机之间通信是从A直接发送到B;单实际上,数据传输时需要中间需要经过很多个中间设备;
在转发中也面临着很多问题:
- 怎么保证把数据交给下一个主机
- 转发中如何进行路径选择,目标主机定付
- 转发过程中出现错误,或丢失问题
- 送达后要如何使用这些数据
将数据可靠的从A送到B,每一个问题都需要有协议来解决;
网络的解决方案 -- 网络层状结构;软件上绝大多数的解决方案都是层状的;这样可以完成软件的解耦,对软件的维护非常方便(更新、替换、优化等) ;
3. 认识网络协议
在教材中将网络协议分为7层:OSI七层模型
对于程序员来说(日常开发中),除去物理层,只将其看作为四层:
- 应用层(应用层、表示层、会话层合并为一层)
- 传输层
- 网络层
- 数据链路层
针对上述网络传输的中的问题,每层都进行了针对性的解决:
网络和操作系统的关系:
用户想要使用网络的功能,不是直接使用网卡,而是使用网络协议栈,而核心的协议是在OS内部的,所以要想使用网络就必须通过OS,网络协议栈和OS是一体的;
虽然不同的操作系统可能在网络协议栈的实现细节上有所差异,但它们都是根据相同的网络协议标准来实现的;也就是说,不同操作系统的网络协议栈实现都是基于相同的网络协议标准;以确保不同OS的计算机之间可以进行有效的网络通信;
4. TCP/IP通信过程
应用层,属于用户进程(应用程序),应用层之下属于内核;每经过一层协议就需要封装一层报头;举个例子:我们在网上买快递,快递送来的时候只有快递吗?不是还会有快递盒子快递单;快递单本身是一种约定,就是一种协议;在进行长距离发送的时候,实际收到的:快递 = 快递单 + 内容;多出的部分(快递单),一般称之为特定协议对应的报头网络通信也遵循这一规则;
如何用C语言表示这个“快递单”?
struct XXX {
...
}
协议通常是用结构化字段表征的。这个结构化字段定义的对象,我们称之为协议报头;所以在进行数据转发时,都会多一部分,多出的部分就是报头;发送数据的时候,client发送数据把数据添加报头serve端收到携带报头的数据,由于它们都遵循相同的网络协议栈,所以serve端也认识这些字段这也就是协议;
计算机接收到数据后,再次经过网络协议栈,将数据包进行一系列的解包:
对于每层协议都要解决两个问题:
- 如何将报头和有效载荷分离
- 如何将有效载荷交付给上层
5. 局域网通信
假设一个局域网中有以下设备:
在同一个局域网中的,两台主机可以直接通信;比如:A要给E发送消息其实是可以直接发的;
每一个网卡,都有mac地址;长度为48位,即6个字节,一般用16进制数字加上冒号的形式来表示(比如:08:00:27:03:fb:19);
举个例子:
比如在教室中,老师询问张三:“张三你的作业写了吗” ;
张三说:“老师,我写了,只是你没看”;
老师的话在教室里的所有学生都能听到,老师叫张三,那么其他人听到叫的不是他们,那其他人就不会理会(无视此条消息);这里的张三其实就是报头;局域网中通信原理也是如此,A发出的消息,局域网中所有的机器都能看收到,其他机器通过报文头知道不是发送给自己的,那么其他机器就会舍弃掉信息,只有E收到信息,查看发现是发给自己的,那么就会对消息进行解析;
A可以和E发消息,那么B也可以和C发消息,在局域网中,每个主机都可以发送消息,那么会出现,多台主机同时发消息,那么就会导致数据碰撞;
在局域网中通信都是通过光电信号,很容易受到干扰,多条信息的光电信号混在起,谁也无法收到信息,一旦数据发生碰撞,数据就直接废了;
在局域网中,我们一般叫做碰撞域数据发生碰撞,发生碰撞的主机就要碰撞避免,停止发消息;也就是说:要正确的发送数据,;任何时刻,只允许一台主机在局域网中发消息;为了解决这样的问题,就可以通过交换机;
局域网就是一个临界资源;碰撞检测和避免,本质就是完成互斥访问;
6. IP地址&&Mac地址
在电脑上查看到的192.168.xxx.xx类似这样的IP地址;[0,255].[0,255].[0,255].[0,255]点分十进制ip地址,c/c++中一般都是字符串;
ip地址:1.公网ip;2.内网ip;日常使用的基本都是内网ip;
ip地址用来表示互联网中唯一的一台主机(这里的ip一般称为公网ip);在网络中4个字节即可表示一个ip地址4*8= 32个bit位;
如何表示ip?比如:
strutc ip_struct
{
uint8_t p1;
uint8_t p2;
uint8_t p3;
uint8_t p4;
};
192.168.xxx.xxx 字符串转化为 uint32_t
struct ip_struct ip;
ip.p1 = 192;
ip.p2 = 168;
...
以点为分割符,将数字转化为uint8_t类型使用时:uint32_t *p= &ip;
uint32_t转为字符串:
(struct ip_struct)&ip->p1;
(struct ip_struct)&ip->p2;
(struct ip_struct)&ip->p3;
(struct ip_struct)&ip->p4;
然后将取到的每个uint8_t转化为字符串类型,添加点分割;
如何理解IP地址和Mac地址?
举个例子:
唐僧取经:
唐僧去取经,到达女儿国,在问路时都会说:“贫僧自东土大唐来,去往西天拜佛求经”,然后问路下一站该怎么走; 问路时都会告诉别人,他们上一站从哪里来,接下来下一站怎么走;
唐僧在取经问路时有两套地址:
- 唐僧要去哪里——终极目标,永远不变(ip地址);
- 上一站从哪来,下一站到哪去——当下目标,一直在变(Mac地址) ;
结合实际:
封装报文之后把报文发送到以太网中,到了以太网中路由器R就能收到这个报文;路由器R接收到报文之后,就可以识别报文的报头,然后进行解包;路由器R就可以看到报文从主机A来要到主机B;
主机B刚好是路由器R直接相连的主机,路由器R对报文进行转发,但并不能直接交付;需要向下交付封装,添加令牌环的报头 然后发送给主机B;主机B的令牌环驱动程序可以识别接收这个报文,然后对报文进行解包;
在这个过程中会发现,报文只到了网络层(IP协议);根本就没有向上交付;上层也无需关心;这一切都是底层自动进行;
正常的通信必然需要经过多个中间设备:
两台主机的通信,其实就是两个进程之间的通信,对于通信双方:
- 先是通信数据能到达各自的机器上
- 找到指定的进程
ip地址用来标识互联网中唯一的一台主机,端口号用来标识指定机器中进程的唯一性;ip+port 就可以标识互联网中唯一的进程;(ip + port = 套接字);
7. 端口号
如何理解port?
端口号:uint16_t port;端口号是一个16位的数字,用来标识当前主机上唯一的一个网络进程;
每个进程在OS中都有自己的pid(进程ID),那为什么还要使用port呢,为什么不使用pid进行标识?其他模块(进程管理)和网络进行解耦;
进程和端口号的关系:
- 一个进程可以和多个端口号相关联吗?可以
- 一个端口号可以和多个进程相关联吗?不可以
端口号是用来标识进程的,一个进程可以有多个端口号,但是多个进程不能共同使用同一个端口号;比如:一个人可以有很多证件:学生证、身份证、教师资格证...;比如:身份证不能被多个人所使用同一个吧,一个人的身份不能被多个人使用,这是不合法的;
8. TCP && UDP
- TCP协议可靠通信;做更多的工作(也更为复杂)
- UDP协议不可靠通信;简单(适用于对数据可靠性不高的场景)
他们没有什么好坏,只是特点不同,根据具体场景进行取舍选择;
9. 网络字节序
计算机存储数据时分为两种:
- 大端存储
- 小端存储
数据是 0x aa bb cc dd
不同的机器存储的方式可能不同;在网络通信中,发送数据不看什么大端小端存储,都按内存地址从低到高的顺序发出;大端机发送顺序:0x51、0x52、0x53、0x54;
接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;两种存储方式发送的数据顺序:
- 大端存储:aa bb cc dd
- 小端存储:dd cc bb aa
如果就直接这样发送数据,小端机发送的数据是dd cc bb aa;那大端机收到的就是:dd cc bb aa;顺序刚好相反;
所以就需要有一个规定,网络规定:所有到达网络的数据,必须是大端,所有从网络收到数据的机器都会知道数据是大端;大端可读性比较好
总结
以上便是本文的全部内容,希望对你有所帮助,感谢阅读!