发表于: 2018-01-06 23:53:28

2 560


今天完成的事情:

什么是tcp/ip协议?TCP的三次握手指的是什么,为什么一定要三次握手,而不是四次或者是两次?

tcp/ip协议是TCP(传输控制协议)和IP(网际协议),提供点对点的链接机制,将数据应该如何封装、定址、传输、路由以及在目的地如何接收,都加以标准化。它将软件通信过程抽象化为四个抽象层,采取协议堆栈的方式,分别实现出不同通信协议。协议族下的各种协议,依其功能不同,被分别归属到这四个层次结构之中。

TCP:面向连接的、可靠的字节流服务

在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP

TCP使用校验和,确认和重传机制来保证可靠传输

TCP给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复

 

所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。

在自顶向下方法 3.5.6 TCP连接管理(中文第6版第169170页)

三次握手:

使用java socket发送请求,打断点,debug模式

                                             

wireshark进行抓包

可以看到三次TCP连接

1A发,B收,B知道A

2B发,A收,A知道B发收

3A发,B收,B知道A

为什么需要三次,因为双向验证,防止对失效请求,建立等待/连接,消耗资源。

A B  

AB的地址

SYN

A.seq=x

seq=x 表示AB发送的字节流的初始序号,实际上没有A. 这为了方便

SYN=1ACK=0表示该报文段为连接请求报文。A端完成,进入SYN_SEND状态,看

B接收到:

B收到数据,B知道A能向自己发数据,而且知道了A发过来的字节流的初始序号。

B又设置了一下:A.seq+1 B.ack=x+1, 表示B要告诉A我接收到了序号x的字节流,下一个字节流应该是x+1的。

B又自己初始化B.seq=y,表示自己作为服务端,发送字节流的初始序号。

B A

把上边说的数据发送:

AB的地址

SYN ACK

B.ack=x+1    B.seq=y

SYN=1ACK=1表示该报文段为连接同意的应答报文。

B还进行了缓存,为建立连接做准备,进入SYN-RCVD状态。B端完成,等

A接收到报文:

A看到SYN ACK知道B同意连接。

A看到B.ack=x+1,知道B成功处理了自己的上一个字节流,也就是B可以接收。

A看到B.seq=y知道B也可以发送。

所以,A就设置了自己下一个字节流序号 B.seq+1(x+1) A.ack

     然后再设置下自己希望服务器发送的下一个字节流序号 B.seq+1(y+1) A.seq

A B

AB的地址

ACK

A.ack=x+1    A.seq=y+1

没有SYN了,SYN=0

B接收到数据,

看到A.ack=x+1  A.seq=y+1,说明A已经成功接收报文并做了处理。

那么就可以建立连接了。

 

三次握手这个说法不好,其实是双方各一次握手,各一次确认,其中一次握手和确认合并在一起。

这其中最要紧的就是 报文的验证(双向机制),如果我们设计一个单向验证的的通讯协议,那么就没有必要三次握手了。两次握手可以搞定这个协议。但是这个协议太浪费资源了。

springMVC

什么是servlet

假如sun公司没有制定servlet规范,那我们怎么写服务端程序呢?

我们可以从0开始写socket,使用io从端口监听字节流,自己写好如何建连接,如何处理报文,如何发送报文,这些属于HTTP协议的最基础的操作。但是这一部分,sun公司已经写好了socket,我们可以直接用,当然你非要从头实现一遍,那真的就太厉害了。

所以java实现了socket,我们就可以看看怎么用这个socket来写一个客户端的请求:

并不是服务端处理请求的实现。

因为服务端比较复杂,但是原理类似。

最简单的大概步骤如下:首先构建一个请求.class、一个响应.class。再创建一个处理.class(参数包括上面的请求.class、响应.class,只处理一个http报文),然后创建一个web容器,请求过来后,使用这个处理class来处理,?谁来呢,应该是web容器?把字节流封装成请求.class传给处理.class处理.class经过一系列操作,或者找到资源或者返回错误。把结果封装成响应.class,再把这个响应.class转换成响应报文传给请求者。

如果Sun公司不来规范,那么问题就很多了:

这些类包含哪些属性、哪些方法?web处理器和应用之间传递请求.class、响应.class时的时候怎么保证成功?把结果封装成响应.class的时候怎么封装?响应class转换成响应报文的时候也要开发者自己实现吗?


如果每个人实现都不同,那就太混乱了。所以出了Servlet规范,最少要知道 servlet、genericservlet、httpservlet:

 

所以可以这么总结:

sun公司写好了一堆处理http的接口,其他的(写web容器的、开发web应用的)要按照这个接口的规范来写。同时servlect还有一些封装,一些处理http的函数、方法。

servlet规范是一组接口,规定java web应用各个组件之间怎么通信交流。

而一个开发人员写出来,实例化的servlet,就是一个Java对象,这个对象拥有一系列的方法来处理HTTP请求。客户端发送一个HTTP请求,HTTP请求由Web容器分配给特定的Servlet进行处理,Web容器中包含了多个Servlet,特定的HTTP请求该由哪一个Servlet来处理是由Web容器(其实就是个servlet容器)中的web.xml来决定的。

 

jsp又是什么呢?上面我们说要把响应.class转换成响应报文

这一步其实有很多问题:

响应.class 应该包含什么数据?  其实只要有html文件中那些 value就行了,其他的html标签、样式不应该放在响应.class中。


然后讨论转换:

直接写一个响应.class转换为响应报文 方法,这样好吗?

这样太不直观了。比如说发响应报文(客户端接受到会转换成一个html网页),现在从数据库中取出的数据就是几个值,怎么办?难道手动写一个html文本,把这些值插入到对应的位置,然后发给客户端?不可能,这样开发者要崩溃。

这时又有好几种方案可供选择:一种叫html模版,一种就是jsp了,应该还有其他方法。这里单说jsp

有了 jsp,我们又加了一层,并写了一个通用的方法来转化,具体来说:

响应.class的数据,传给一个jsp文件(就是开发人员来编写jsp的过程)。转换的时候,用那个通用的方法,把jsp转为java,再转为响应报文

 

为什么有jsp转化为java类这一步?

可能是历史原因:原来是servlet对象转成响应报文,现在把jsp转为servlet(java ),再转成响应报文


总结如下:

jsp跑视图,servlet做逻辑控制。jsp本身就是一种模板化脚本化的servlet,用来优化html结构的编辑(如果不用jsp脚本标记标识的部分,在web容器转化时会被转换成out打印),servlet就是一个普通类,一旦编译加载后就不能动态替换。jspservlet应该是先经过jsp文件检测,如果有变化就重新生成相应的servlet源代码并编辑加载,没变化就沿用已编译好的源码。servlet一作为逻辑业务定下后一般不需要频繁改动,jsp作为界面输出倒是更频繁改动,而jsp的特性就是为这个设计的。

 

为何不用jsp代替servlet,运行速度,应为jsp要转换为servlet才算正式处理,转换要时间。

详细说下servlet

http://www.runoob.com/servlet/servlet-tutorial.html

http://blog.csdn.net/evankaka/article/details/45151569

先记下,后面再看。

 

明天计划的事情:

用原生servlet实现服务器,搞清楚servlet运行过程、springmvc 处理请求的过程(dispatchservlet)、深度思考、jetty服务器、maven部署

遇到的问题:

暂无

收获:

主要来看原理了,http协议太多了,一个月也看不完,准备看完深度思考相关的,就跳过去,再看看网上总结的。




返回列表 返回列表
评论

    分享到