盼望着,盼望着,发出去的“快递”终于顺着“网线”到达了签收地……
前面,我们探索了Web服务器前面的防火墙、缓存服务器、负载均衡器等设备,现在网络包已经通过这些设备,到达了Web服务器中,现在我们就来探索这一过程。
一台电脑既可以是服务器也可以是客户端,那么客户端和服务器有什么区别?
对于网络相关的那些部分,如网卡、协议栈、Socket库等,客户端和服务器是一样的,它们功能相同,但是用法会有所区别。在连接过程中,客户端发起连接操作,服务器进行等待操作,即它们调用Socket库的程序组件不同。此外,服务器程序可以同时和多台客户端计算机进行通信,这说明服务器程序和客户端程序在结构上是不同的。
服务器程序的结构
服务器程序可以分成两个模块:等待连接模块和负责与客户端通信模块。当新的客户端发起连接时,都会启动一个新的客户端通信模块,这是利用了操作系统的多任务、多线程功能。
接收客户端消息之前,服务器要做相应的准备工作,其中的创建套接字操作是怎么做的?
创建套接字操作的本质是分配用于套接字的内存空间。
要解决这个问题,需要了解服务器程序是如何调用Socket库的。
- 首先,协议栈调用socket创建套接字。
- 通过调用bind将端口号写入套接字中。
- 设置好端口号之后,协议栈调用listen向套接字写入“等待连接状态”的控制信息。
- 收到连接请求之后,协议栈调用accept接受连接。
- 协议栈给等待连接的套接字复制一个副本,然后将连接对象等控制信息写入新的套接字中,并和客户端套接字连接在一起。
- 这时服务器的等待连接模块会启动与客户端通信模块,然后将连接好的新套接字转交给与客户端通信模块。
- 原来的等待连接的套接字继续等待(调用accept组件)。
服务器如何识别包该用哪个套接字?
要确定某个套接字时,可以用以下四种信息:
- 客户端IP地址
- 客户端端口号
- 服务器IP地址
- 服务器端口号
然而,应用程序和协议栈之间是用描述符来指代套接字的。
- 等待连接的套接字中没有客户端IP地址和端口号
- 使用描述符这种信息比较简单
服务器的接收操作过程是怎么样的?
大致和客户端发送操作类似,下面简单回顾一下。
- 网卡将接收到的信号转换成数字信号,校验FCS后保存到网卡缓冲区,对分片的包进行重组。
在这个过程中,服务器的CPU不是一直在监控网络包的到达,而是在执行其他任务,网卡需要通过中断将网络包到达的事件告知CPU,这样网卡驱动会切换为操作系统,操作系统调用TCP/IP协议栈,由协议栈继续进行接收操作。
- 根据IP头部的协议号字段,将包转发给相应的模块(假如是TCP模块)。
- TCP模块响应“三次握手”建立连接,收到数据包后,将数据转交给应用程序。
- TCP模块“四次挥手”断开连接,套接字在一段时间后被删除。
服务器怎么解释请求消息并作出响应?
实际上,客户端看到的服务器目录是虚拟的,和实际目录不同,这是为了防止服务器文件暴露。服务器收到请求消息后会将内部实际的目录名和供外部访问的虚拟目录名进行关联。
服务器也可以设置访问限制,例如只有百度文库VIP才可以下载百度文库的文档,可以通过这些条件实现:
- 客户端地址
- 客户端域名
- 用户名和密码
旅途的终点——浏览器接收响应消息并显示内容!
服务器返回的数据中包括文档、图片、视频等多种类型,客户端原则上是根据响应消息的Content-Type头部字段的值来区分。
类型 | 含义 |
---|---|
text | 文本 |
image | 图片 |
audio | 音频 |