接收端--服务器详细阐述
本章是‘网络是怎么连接的--读后感’第六章(该系列完)
前言
本章是系列博客的第五章;第一章讲数据发送的场景;第二章主要讲叙消息是如何发送出去的;第三章主要阐述数据包在客户端局域网中的传输;第四章详细阐述数据在互联网中是如何传输的;第五章讲接入端局域网中的通信;最后一章主要介绍服务器。
实现需求
本章介绍服务器;介绍服务器的整体结构;包接收操作;请求消息的应答操作;最后对浏览器接收到响应消息后的显示进行说明。
- 服务器概述
- 服务器的接收操作
- 服务器收到消息后对请求消息进行解释并作出响应
- 浏览器接收响应消息并显示内容
正文
一、服务器概述
服务器在硬件构成上和终端电脑类似,使用的协议,库等也和客户端高度统一;这是由于互联网早期是没有客户端和服务器区分的,两者的最大区别是在功能上:“客户端发起连接,服务器等待连接”,服务器等待连接的过程如下:
- 服务器在进行初始化的时候会通过操作系统Socket库的socket方法来创建一个套接字;
- 随后会调用bind方法将端口号写入套接字(注意服务器的端口号根据服务器应用程序的种类按规则确定如web服务器默认80端口);
- 上一步设定了端口号,在客户端端口号也是这样设定的(因此套接字就和通信的硬件端口实现了关联,通过端口就能确定套接字);
- 再通过listen方法调用套接字的描叙符,将套接字状态变为等待连接状态(套接字创建之后后面的方法都是通过描叙符调用套接字的,后面说明原因)
- 然后当客户端的包过来后,就返回响应包并开始接受连接操作;此时协议栈调用accept复制一个等待连接的套接字副本,并将连接对象等控制信息写入该套接字(发送端和接收端ip端口,序列号,tcp窗口信息等,记住连接就是双方交换套接字信息过程,最后两端的套接字都会有所有控制信息);
- 最后将客户端的套接字和这个新套接字连接起来;(以上步骤都是在服务器的等待连接模块在实现的)
- 后面服务器会创建新的任务或进程,并将连接了客户端的这个套接字传给该通信模块;(操作系统创建应用程序原理有关,可以理解为程序是复制出来的,通过查看pid,ppid等可以确定,所有程序的来源都是最初的一个初始化程序);
- 此时最初在等待连接模块中创建的套接字仍保持着等待连接状态;
- 如果有新的客户端通信,则重复上诉操作;
- 说明:也有些服务器会首先创建好多个通信模块,客户端的请求过来,就无需在创建应用程序了,因此响应会更快;
补充下:在创建新套接字环节时,端口也是关键点;由于端口是用来识别套接字的,理论上一个套接字应该对应一个端口;实际不是这样的,实际上套接字是由:“接收方IP和端口,发送方IP和端口”四个要素来共同确认的,因此在服务器中不同的程序可能有相同的端口。
示例图如下:
二、服务器的接收操作
通过前面的知识可以了解到到达服务器的包一般是以光信号/电信号过来的;通过转化设备能将光信号转换成电信号传给服务器;服务器的网卡接收到电信号后在内部的PHY模块将电信号转为通用电信号传给MAC模块;MAC模块在将电信号转换为数字信号(含时钟信号的),同时分离时钟信号,根据时钟信号同步还原出原始请求的数字信号;然后在根据末尾的FCS来进行效验错误,超出范围说明异常则丢弃包(发送端就会重发);没有错误则检查MAC头部确认接收方MAC地址,如果是发给自己的则将数据保存到网卡的缓冲区,否则丢弃;至此在网卡中的工作就完成了;(到这包的mac头和其他被验证的头都会被丢弃)
到达网卡缓冲区后;网卡通过中断使得CPU切换到网卡任务,cpu启动网卡驱动程序将数据包网卡缓冲区的包取出来,并根据以太包头部(mac头部)的以太类型来判断协议种类,这里使用的是ip协议;因此会调用tcp/ip协议栈将包转发给他。
至此包就转发给协议栈了;在tcp/ip协议栈中IP模块会先工作,检查包的IP头,确认接收方IP是否是自己,如果是在根据IP头的信息判断包是否有切片;如果有则将包存在内存中等所有被切片的包到达后在拼接在一起;(如果包不是发给自己的,如果服务器开了路由功能,则会和路由器一样将包转发);
然后IP模块会检查IP头部的协议号字段,并据此将包发送给对应的模块(协议号是6就发TCP,11就发UDP);
假设上方IP模块将包发送给了TCP模块;第一个包一般是控制连接的包(也就是SYN参数为1),然后根据端口就能确认连接的套接字(这在本章第一节讲了不在重复),同时会协议栈控制操作系统分配发送缓冲区和接收缓冲区;然后生成代表确认的ACK号,结合套接字的其他控制信息生成TCP头部委托IP模块讲包发送给客户端(不在重复讲);这个包到达客户端后,客户端会响应ACK确认机制。(数据在tcp中还有组合机制,根据序号可将切割的包组合起来);最后处理完的数据包存在接收缓存区中,然后被cpu调用read方法转交到应用程序的内存中;
tcp断开操作;前面有不重复讲。
三、服务器收到消息后对请求消息进行解释并作出响应
上节已经讲到数据传递给应用程序了,在服务器中TCP过来的数据包也能通过read方法获取包内的http消息并转给应用程序;然后根据http协议解析消息的内容,一般能获取请求方法,请求的地址,及参数;如果请求的是html,图片等静态文件,直接根据请求的地址找到资源所在的路径,直接返回即可;还有一种url指定的请求对象是cgi程序,这样的话就会讲http消息中的数据作为参数传递给cgi程序,程序处理后讲数据返回给web服务器,然后web服务器的应用程序在根据write方法将响应消息传给协议栈(写给tcp);协议栈在根据套接字的描叙符确定通信目标,然后经过一系列操作将包发送出去。
注意,由于web服务器出于安全考虑,请求的资源地址一般是虚拟地址并不是服务器中资源的实际目录,因此当请求到服务器后会讲请求的虚拟目录转化为实际目录;
补充:web服务器具有访问控制机制(权限管控,限定资源的访问对象);控制规则主要有三种:
- 客户端IP(这种只需要检查请求的IP是否有访问权限)
- 客户端域名(先通过web服务器向web端的dns服务器发起查询请求根据IP查域名,然后对检查到的域名判断是否有访问权限即可,有反查机制如图)
- 用户名密码(如图)
四、浏览器接收响应消息并显示内容
浏览器接收消息和服务器接收消息的方式是一样的,HTTP消息到达浏览的内存中后,首先需要对接收的http消息的类型有个判断,这通过http消息头部的content-type参数可以实现;(常见的主类型有8种,每种又对应一定种类的子类型如下图)
不同的数据类型通过使用不同的程序来解析渲染,如html,图片等数据通过浏览器本身就可以渲染因此就能直接将数据展示出来(注意实际的显示是由操作系统完成的,浏览器根据收到的http响应消息,对操作系统发出指令来实现显示操作);因此确认数据类型,根据类型调用合适的渲染程序,进而来显示内容。