前言:之前因为做项目和找实习没得空,计算机网络模块并没有写成博客,最近得闲了,想把计算机网络博客补上,方便日后参考与复习。
目录
一,两个独立的计算机该如何通信?
二,数据的流动
三,socket基础
1)端口号
2)网络字节序
一,两个独立的计算机该如何通信?
假如有两台没有任何关联的离线计算机,我们想要从0实现计算机之间的通信,我们会碰到哪些关键的问题呢?
首先肯定是两台计算机的实际0/1信号无法交流,这是我们碰到的第一个问题。解决办法一般来说就是通过物理媒介,或者无线电波的方式。这是最基础的通过物理设备,一1/0形式发送接收数据,被称为物理层。
但是物理层发送消息,消息一定会准确的到达吗?不会发生碰撞,或者信号衰弱丢失等情况吗?答案是肯定的,那怎么办?这就必须提到数据链路层了,数据链路层在物理层之上,会给数据帧头,帧尾,利用如帧校验序列(FCS)保证物理传输信号的完整性和顺序性,利用ACK或者编号保证不检测出数据包丢失要求重传,这不就解决了1/0数据的可靠传输了吗?
我们解决了1/0信号的传输,但是我们一台主机该如何找到另一台主机,可能有人说你前面不是说有物理设备相连吗?但是我们都知道,世界上主机数不胜数,基本上主机都有物理设备相连,我们还是要想办法找到指定的主机。负责两个主机之间寻址的是网络层,其实数据链路层也有MAC地址,有很多原因,我主要说几点。1,网络层独立于数据链路层,可以屏蔽底层设备差异,如数据链路层也有很多不同物理接口(如以太网、Wi-Fi、光纤等)和不同的数据链路层协议(如以太网协议、Wi-Fi协议等)。2,MAC地址是厂商制造电脑时随机和无序分配的,并且一般不支持更改。
在网络层上面是传输层,其实我之前也一直有一个问题:,数据链路层也能进行一定的可靠数据传输,为什么还要传输层?如果把传输层的功能集成到数据链路层,除了会导致这一层太复杂了,可行吗?
我搜集信息,我觉得这些回答让我满意。集成后的数据链路层可能无法适应不同网络环境和应用需求的变化,导致可扩展性受限,太复杂了,也难以维护。数据链路层只考虑相邻节点通信,如果跨网络的话,可能数据链路层协议不同,我们在本层进行协议的转换是复杂不好操作的,如果区分出来不就是一个”传输层“吗?而且数据链路层在网络层下,进行不同网络通信的时候,数据的可靠性是无法保证的。传输层的特性我会在后续博客详细解说。
我们已经有了基本的通信能力了,但是我们通信肯定是有目的的,就像我们玩手机不可能就是无聊的发一些1/0信号吧,我们需要使用各种应用,例如QQ,酷狗音乐,王者荣耀等,这部分又具体分为三层。
会话层在传输层之上,会话层进行通信管理,负责建立和断开连接(利用传输层),以及管理传输层以下的分层。
表示层又位于会话层之上,主要负责对应用等产生的数据进行格式转化(由设备固有格式转化成网络标准数据格式),以及进行加密、解密、压缩、解压缩等处理操作。
应用层在网络通信里面主要是一些针对特定应用的协议和标准,如HTTP(超文本传输协议),FTP(文件传输协议,SMTP(简单邮件传输协议),位于表示层之上。
这个是国际标准协议,虽然很理想,设计也合理,但是因为太过于细分了,而且商业竞争等,国际上通常默认分为五层或者四层模型。五层是把应用层,会话层,表示层合为一层应用层,四层则把数据链路层和物理层也合为数据链路层。功能就是进行整合了,差别本身不是很大
二,数据的流动
从上面描述我们可以得知数据大概是这样流动的
发送数据时,首先应用层确定发送的内容,对数据进行格式等规定,确保对方能够解析内容并处理。然后将数据交给传输层,传输层主要是TCP/UDP,给应用层数据加上报头,报尾,保证数据的完整性和收到后有序处理,以及损坏或丢失重传。应用层封装之后交给物理层,网络层将数据,进行切片和源地址和目的地址等信息添加到报头报尾,帮助数据到达目的地。网络层最后交给数据链路层,保证帧数据的可靠性。你是不是有一个问题,为什么传输层已经保证了数据的完整性,数据链路层,因为传输层保证的是应用层数据完整性,数据链路层是对网络层数据的完整性,二者可以缺一个吗?答案是不行,没有传输层的可靠性保证,无法进行不同网络的传输。没有数据链路层的可靠性保证,数据的内容可能出错,因为传输层只保证数据的完整(不丢包),数据在物理传输过程中仍可能损坏出错。数据的变化如图下,接收到数据后会进行相反的解包操作。
三,socket基础
1)端口号
从前面的知识我们可以知道网络通信寻址是通过网络层,网络层里面最重要的就是IP,主机进行网络通信时的是又在这个网络内(子网,公网)唯一的IP地址,通过IP地址来区分每一台主机(没有说NAT技术,端口转发等),因此先要和一台主机进行通信,我们只需要知道目标主机的目标IP地址就可以找到(具体详解,我后面会有博客讲述)。
但是虽然我们通过IP地址找到了这台主机,新的问题也出现了,我们的主机上一般不会只跑一个应用或者程序吧,假如每个应用在进行通信,例如:QQ,微信,王者荣耀,都可以同时运行。我们该如何判断这条消息该交给那个应用处理,这时候就引入了端口号,端口号是传输层一个2字节的无符号整数,用来区分主机进程的标识符,一个进程可以有多个端口号,但是一个端口号只能属于一个进程,前者完全没问题,后者如果一个端口号属于多个进程就会出现二义性。
2)网络字节序
#include <arpa/inet.h>
//将主机序列转换成网络序列uint32_t htonl(uint32_t hostlong);uint16_t htons(uint16_t hostshort);
//将网络序转化成主机序uint32_t ntohl(uint32_t netlong);uint16_t ntohs(uint16_t netshort);
//注:如果主机序列和网络序列一样不会进行转换,可以放心使用
本来想把TCP和UDP简单的介绍一下,但是怕自己一介绍就停不下来了,因此期待我的下一篇文章socket编程吧。本文到此结束,如果大家有所收获,不如点赞和关注。