【Linux】网络基础和网络套接字的概念
上面我们讲了网络基础的概念以及网络套接字的一些概念,这些知识是为了我们下一篇编写UDP服务器而做准备的,由于网络相关的知识都比较抽象,所以还是希望大家可以尽量的去理解网络中各种名词的解释。
一、网络的发展及其网络中的概念
刚开始的计算机大多处于独立模式,也就是说计算机之间相互独立。等到网络出现的时候就出现了网络互联,多台计算机连接在一起完成数据共享。随着发展计算机越多越多就出现了局域网LAN,这个局域网LAN可以让多台计算机通过交换机和路由器连接在一起,但是由于局域网的范围不够广泛,不久后就出现了广域网WAN,广域网WAN将远隔千里的计算机都连接在一起。所谓“局域网”和“广域网”只是一个相对的概念,实际上我们完全可以将大的广域网也看成局域网。
下面我们认识一下网络协议:
“协议”简单的说就是一种约定。计算机之间的传输媒介是光信号和电信号,通过“频率”和“强弱”来表示0和1这样的信息,要想传递各种不同的信息,就需要约定好双方的数据格式。这就比如我们的语言一样,各个地区都有自己的方言,交流的时候会让很多人听不懂,但是普通话的出现就解决了人与人沟通听不懂的问题,普通话就是人与人之间的协议。(定制协议可以尽可能的减少通信成本)
而在网络协议中,我们又分了好几个层次,为什么要分层呢?因为分层最大的好处就是封装。
OSI七层模型:
网络传输基本流程图:
因为物理层我们考虑的比较少. 因此很多时候也可以称为 TCP/IP四层模型.
两台计算机通过TCP/IP协议通讯的过程如下所示:
下面我们通过上图来谈谈局域网中协议报头的概念:
1.协议报头: 协议在上图中每一层都会有,而每一个协议的最终表现就是协议都要有报头。
怎么理解报头呢?我们举个例子:比如我们网购买了一个水杯,等卖家给我们发货到我们手里时除了水杯还有快递盒和快递单,这个快递单就相当于我们的报头,快递单不是给我们买家看的,是给快递员看的,报头也一样。
2.协议通常是经过协议报头来表达的,就像快递单上的格式都是卖家的地址电话和买家的地址电话一样。
3.每一份数据最终在被发送或者在不同的协议层中都要有自己的报头。比如我们买的水平可能会附带水杯的说明书,这个说明书就是数据自己的报头。
下面是局域网的概念:
1.两台局域网的主机能够直接通信。
2.局域网通信的原理:每一台机器都要有自己的“名字”,每一台主机都有网卡,每一张网卡都有自己的地址,MAC地址(表明自己在局域网中的唯一性)。
我们在linux中输入命令:ifconfig就可以看到自己的Mac地址:
ether后面就是Mac地址,下面我们谈谈局域网是如何实现通信的:
如上图所示,一共有7台主机,每台主机依靠物理地址(MAC地址)区分,当MAC1这台主机给Mac6这台主机发送消息时,所有的主机都会看到这条消息,比如这条消息传到了Mac2中,Mac2发现这个消息是要发送的地址是MAC6的(主机会在自己的底层协议做判断,可以判断出消息是不是发给自己的,如果消息不是自己的那么就将消息丢弃),所以不会对这个消息做出回应,只有MAC6收到了消息。
如上图所示,当左边的用户要给右边的用户发送一条“你好”的消息时,实际上这条消息会从应用层向下交付到传输层,再从传输层交付到网络层,然后交付到链路层,我们之前说过,报头在每一层都会有,所以这条消息每次在被向下交付的过程中都会被加上报头,如下图:
到链路层后会将这条消息通过以太网发送到网络中(注意图中只有两台主机,实际上如果有多台主机这条消息发到网络中后每一台主机都会判断这条消息是否是发送给自己的,如果不是就丢弃)。这样我们就将这条消息发送到另一台主机的链路层中:
注意以上的过程类似于栈结构,A主机链路层最后封装的被B主机先拿到。
这条消息我们将它分为报头 + 有效载荷,在B主机链路层向服务器交付报文的时候会做一个工作,那么去掉报头(注意:每一层只能去除每一层特定的报头,比如链路层的桃心报头只会被B主机中的链路层去掉)。
经过层层去掉报头的操作后,我们的消息最终就会被B用户所收到。 所以整个过程就是:当我们发送消息时,会自顶向下(应用层到链路层)添加报头,接收消息时自底向上(链路层到应用层)去掉报头。而上面添加报头的过程被称为封装,去掉报头的过程被称为解包。
注意:在网络协议中,我们可以认为同层协议在直接通信,也可以理解为向下交付,这是两种不同的认知并且并不冲突。
下面我们看看带路由器的数据传输过程:
我们可以看到路由器既属于左边又属于右边,相当于将图上两台主机做了连接,如下图所示:
用户A发送消息还是像前面那样先要从上向下封装报头,不同的是消息经过以太网驱动程序封装报头后直接交给了路由器。
我们可以看到,要交给路由器必须从底向上交付,一旦从底向上交付就必须解包,所以路由器拿到的是解包以太网报头后的消息,然后路由器发现这个消息要发到右边的主机,这里还是要先给到右边主机的最底层,由于是从顶向下所以又需要添加报头,如下图:
这里的流程就和我们前面讲的一样了直接从令牌环驱动程序开始解包向上传输消息最终被右边的用户收到:
这里我们讲一下局域网中的以太网和令牌环网:
以太网:只允许一个主机在任何一个时刻在局域网中发送消息,否则发生碰撞(局域网就是碰撞域),比如前面我们讲的7个主机的例子,在那个例子中不能如果是以太网则同一个时间点只能有一个主机在局域网中发送消息。
令牌环网:还是7个主机的例子,但是不同的是只有获得令牌的那个主机才能发送消息,这里的令牌与我们的互斥锁类似,就像只有申请到锁资源才能访问数据一样。
下面我们学习一下网络中的地址管理:
ether后面就是mac地址
inet后面就是IP地址,如上图所示。
下面我们认识一下网络编程套接字的相关概念:
理解源IP地址和目的IP地址
为了好理解我们举一个例子:唐僧从东土大唐到西天取经,在这途中他要先从黑风岭到女儿国,这里的目的IP地址就是女儿国,源IP地址就是西天(可以理解为源IP就是终极目标)
端口号(port)是传输层协议的内容.
我们在学进程的时候说过,进程的pid是标识进程的,那么我们为什么还要用端口号来表示进程的唯一性呢?这里我们先说一个概念:网络通信的本质就是进程间通信(进程间通信有两个前提:1.需要让不同的进程先看到同一份资源(网络通信中这个资源就是网络)2.我们说过通信实际上就是IO,所以通信就两个目的:我把我的数据发出去或者我收到别人给我发的数据) ,这也就是为什么我们上面端口号的概念中出现了多次进程这个名词。1.实际上虽然pid是表示进程的,但是不是每个进程都进行网络通信的,所以不用pid来替代端口号。2.最重要的是,系统是系统,网络是网络,我们不能将他们的接口混为一谈。3.网络中客户端每次都能找到服务器进程,这就说明了服务器的唯一性不能做任何改变,所以我们的端口号port不能随意的去改变。(进程的pid每次重新运行程序都会不一样)。通过以上3点,我们解释了为什么网络通信需要端口号的存在。IP + port
我们刚刚说了一个端口号只能被一个进程绑定,那么一个进程可以绑定多个端口号吗?答案是可以。因为我们要的是从端口号到进程是唯一的,一个进程绑定多个端口号,那么从端口号到这一个进程也还是唯一的。
TCP协议特点:
UDP协议
网络字节序
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);
注意socket就是套接字,套接字可以分为:
1.网络套接字(应用于网络跨主机之间通信并且还支持本地通信)
2.原始套接字(适用于抓包等工具)
3.unix域间套接字(只能够本地通信)
我们在上面的套接字编程接口中可以看到sockaddr这个类型,下面我们讲讲它的结构:
总结
上面我们讲了网络基础的概念以及网络套接字的一些概念,这些知识是为了我们下一篇编写UDP服务器而做准备的,由于网络相关的知识都比较抽象,所以还是希望大家可以尽量的去理解网络中各种名词的解释。
更多推荐
所有评论(0)