文章目录
关于专栏----WebServer二三事
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HZqt0PnA-1604666118212)(https://img.shields.io/badge/LWebServer-%E5%89%8D%E8%A8%80-yellow.svg)]
在现代网络应用程序所使用的两种主流的体系结构: 客户机/服务器体系结构(CS) 和 对等体系结构(P2P) 中, Web应用程序属于典型的CS架构。这个相信大家都了解,而平时我们进行的服务端编程,大多数程序员习惯于使用较高层次的组件,框架,中间件等,使用便捷,能快速的完成功能点开发效率高,这些框架的使用使我们的开发变得简单,我们只需专注于业务,毋庸置疑是事半功倍的做法。
但是在学习计算机网络,操作系统等原理性课程时总感觉和在开发过程所学的框架知识总存在着飘忽不定的隔阂------ 连贯不起来!
而这些问题的源头就是,框架/组件为我们"做"了太多事情,这不是不好,相反这大大解放了工作量,但是我们却也失去了对一些底层概念的理解, 网络通信原理或者是 IO交互过程等,
如何连贯?,我认为理解通信原理很关键,所以我通过实现简单服务器,去了解通信细节,协议,高性能原理,而这些底层内容对于框架和语言来说是通用的,所以对我学习框架或者是语言也是降维打击。
学习网络通信就不得不说到 Socket编程。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fCByZAXm-1604666118213)(https://img.shields.io/badge/LWebServer-Socket-yellow.svg)]
首先得了解网络应用程序进行通信的是进程而非程序,在TCP/IP参考模型中
不同的端系统上的进程通过跨越计算机网络交换报文(message)而实现相互通信。
而具体的跨越过程这里不做详细探讨,可以通过计算机网络至顶向下方法这本书进行详细了解。
客户机进程和服务器进程
对于Web应用来说,进程间的通信存在于客户机和服务器之间,进程简单理解为运行在端系统的程序,而客户机进程比较常见的就是浏览器,而服务器进程为Web服务器,比如Apache,Nginx,Tomcat等,
那我们写的WebApp在这里面充当什么角色?
这里就体现前面说的,我们写的Web程序是基于一些组件框架或者中间件上建立的,其中复杂的通信原理被Web服务器封装,拿Tomcat来说,作为Servlet和JSP的容器,它负责接收HTTP请求,并把请求转送给对应的Servlet,然后Servlet将处理好的结果(响应)传回Tomcat,由Tomcat响应到客户机。我们开发的时候不用关心浏览器是如何和我们的Web程序建立TCP连接,协议如何解析。Java Web之Servlet的创建和详细原理
Web服务器通过对套接字(Socket) 的封装实现进程间的通信,使我们在应用程序编程时不感知套接字层。
上图可以看出操作系统通过提供Socket来为进程提供通信能力,而大多数应用端程序是基于通用组件编程,Socket层相对来说是透明的,但是在构建高性能应用程序时我们不得不去设置组件参数,优化组件性能,甚至是实现某个满足我们需求的特定组件,这时对底层通信接口的理解就变得十分重要了。
进程与计算机网络间的接口 ----------------Socket
网络通信是进程间报文传输的过程,从一个进程向另一个进程发送报文必须通过下面的网络,进程通过操作系统提供的称为套接字(Socket) 的软件接口在网络上接收和发送报文。其实是进程间通信的抽象机制,
这里暂时不讨论它在不同的操作系统的具体实现(在后续深入理解文件描述符时探讨)。
如图所示,Socket是同一台主机内应用层与传输层之间的接口,也可以将Socket称为应用程序和网络之间的应用程序编程接口(API) ,应用程序开发者可以控制Socket在应用层端的所有东西,而对该Socket的传输层端的控制却仅限于:
- 选择传输层协议;
- 设定几个传输层参数,如最大缓存,最大报文长度MSS等。
Socket相关系统调用
这里主要是记录Linux下的Socket的系统调用函数,各种OS下其实都大同小异,其实JDK中为我们提供的函数,也是基于这些系统调用(syscall)的封装。
socket()
socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行