再谈长连接和短链接,http

我们都知道http协议中,一次TCP连接需要三次握手,这些东西不作另外赘述,想了解的小伙伴,可以参考

本博文:

https://www.cnblogs.com/cyh2009/p/10601990.html

一、长短连接的概念

1、第一种

首先,我们要知道长连接的意思是什么

假设,有个人在浏览网页的时候,发现有个在线的聊天窗口,聊天的时候,点击窗口,则网站方的工作人员会弹出来,和我们保持连线,

又有,有人上某宝浏览商品,发现一件商品,让他停下来留意了一会儿,于是他点进去,和客服人员开始交谈了起来

上面两种场景都有个特点,就是在“聊天”这个动作开启之前,首先是先打开聊天窗口,类似于连接,这样的一个动作,

等连接好了,就开始聊天了,期间可以聊一个小时,也可以聊一天,时间一般并没有什么限制,

2、第二种

还有一种场景,你打开了某宝,你对于你上周在线购买的手机的质量感到不错,于是你给了一个好评,当然,可能过了一会儿,你的评论下面,就会有其他买家来询问,手机的待机时间有多久,或者掌柜的对你说声谢谢,但所有的这些评论,被你发现的时候,可能你需要刷新页面才能发现,又或者页面提示你,有新评论啦的时候,你才会发现,当然你看到评论的时候,你一时半会儿不知道该怎么回答这些个问题,于是你把浏览器关了,等到下个礼拜再打开网页,再进行回复

 

你发现,1和2的最大区别是什么呢?

显然,1的聊天过程中,如果发生了中断,则仍需要再次打开在线聊天窗口等待对方连接,保持连通之后,则可以继续对话,所以你一句我一句这样的聊天方式,是建立在一次连接之后进行的,

而2的聊天过程中,即便是关闭网页,再打开,评论的过程没有什么影响,当你评论的同时,有可能已经有好几个评论在你的下方了,但是这些多个评论,你一时半会儿是看不到的,?什么?怎么看到的?当然是等你评论完后提交刷新页面的时候,其他的数据才缓冲过来

显然,数据的刷新是需要我方刷新后才能看到的,而我们不刷新,不向服务器提交的话,服务器是不会提供连接,提供刷新的。再例如,即便你不评论,你再登上半天,说不定有10个人来评论你了,但是你不刷新一下页面,你的页面上面依旧没有显示

所以最大区别在于,客户端获取服务器的服务是否需要重新建立连接,这是最大的区别。

而且还能够发现一个明显的大不同,长连接过程中,建立连接后,客户端和服务端在不断的通信,且只要连接建立中,没有断开,理论上是可以不断来回通信的,(不考虑数据空间容量)

短连接,没有断开连接之前,是不会出现反复的数据交换的,注意,这里不能叫信息,这里只能是消息,信息是消息中所包含的信息量,有大小之分,而基本是数据包的通信,为啥不会出现反复,因为再次的数据请求是需要再次的建立连接的,如果不再次建立连接,是不能再次发送数据请求的

 

 

二、长短连接的示例

1、长连接示例:

建立连接>>发送数据>>获取响应>>发送数据>>获取响应>>..........................>>发送数据>>获取响应>>断开连接

2、短连接示例

建立连接>>发送数据>>获取响应>>断开连接。建立连接>>发送数据>>获取响应>>断开连接。建立连接>>发送数据>>获取响应>>断开连接。

关键的关键,在于再次发送请求数据,是否需要再次建立连接

 

三、java中的长短连接模拟

1、倘若本地有一个socket服务提供方 (本地服务端)

2、倘若本地也有一个socket服务消费方(本地客户端)

以1和2,来完成这样的实现,如下:

未完待续

 

 

 

代码模拟示例:

1、服务方:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
*
*/

 

public class SocketService {
public static void main(String[] args) {
SocketService service=new SocketService();
service.doListen();
}

public void doListen() {
ServerSocket server=null;
try {
server =new ServerSocket(3001);
while(true) {
Socket client=server.accept();
new Thread(new SocketThread(client)).start();
}
}catch(Exception e) {
e.printStackTrace();
}
}


public class SocketThread implements Runnable{
Socket client;

public SocketThread (Socket client) {
this.client = client;
}

/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
DataInputStream dts=null;
DataOutputStream dos=null;
// TODO Auto-generated method stub
try {
dts=new DataInputStream(client.getInputStream());
dos=new DataOutputStream(client.getOutputStream());
Thread.sleep(5000L);
String data = dts.readUTF();
dos.writeUTF("dsadsa1:"+data);
data = dts.readUTF();
dos.writeUTF("dsadsa2:"+data);
}catch(Exception e) {
e.printStackTrace();
}


}



}
}

 

 

 

2、消费方

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;

/**
*
*/

public class SocketCustomer {
public static void main(String[] args) throws Exception {
new SocketCustomer().exet();
}

public void exet() throws Exception {
Socket socket = null;
socket = new Socket("127.0.0.1", 3001);
//向服务器端第一次发送
OutputStream netOut = socket.getOutputStream();
DataOutputStream doc = new DataOutputStream(netOut);
DataInputStream in = new DataInputStream(socket.getInputStream());
//向服务器端第二次发送
doc.writeUTF("save");
String res = in.readUTF();
String data = "{name:zhangsan, age:22}";
doc.writeUTF(data);
res = in.readUTF();
doc.close();
in.close();

if (socket != null) {
socket.close();
}
}
}

 

 

以上两段代码,暂时还没有完全验证,关于Socket原理,后期给大家作详细讨论和分析,敬请期待

 

四、http是短连接还是长连接呢?

 

说起来我们的http协议的历史,我们知道有http0.9 http1.0和http1.1,回忆一下,

0.9 这个协议只有一种请求方式,就是get请求方式,啥意思?没错,你只能采用链接发访问,所有的请求信息都藏在链接后面,没错,这都称不上藏了

1.0 这个协议规范好了服务器和客户端之间的连接,要求在每次连接中,只保持短暂的连接,什么意思?就是服务器处理完来自客户端的请求后,就必须自动释放掉

神奇不?这个协议居然能 让代码这么运行 ,当然不是啦,规范就是一种双方的约定,而编码的规律,就是根据这些协议的要求,来完成功能。只有符合这些协议要求的代码,或者功能模块,才能在世界范围内推广,你推出了标准,那么其他人当然来遵守,不会做出规则的事。

1.1 早期互联网发展的过程中,受限制于硬件的性能,带宽一时半会儿无法提升,随之而来的是,需求的提升,个人电脑的普及,以及手机设备的普及,浏览网页动辄6到8个连接的消耗,

请求的频繁,导致大量的连接被建立,而1.0时期,因为产生大量的连接,本身是没毛病,但是大量的请求往往在很多时候,是可以重复使用连接的,比如说有一个在线显示疫情人数的页面,这个数字可以设定一个刷新频率是1分钟

或者20秒,在1.0时期,这样的刷新,都是需要每次建立一个连接的,因为1.0就是规定每次刷新完后,将连接释放掉

但每次刷新就建立连接,这样将白白浪费带宽,假如一天的刷新次数有200次,举个例子,但是刷新200次的同时,要建立200次连接,这就问题大了,除非其他事情不干,否则在建立连接刷新的同时,还有其他网页的请求,用户的需求都需要占用带宽,而多出来的这么多重复的请求将给其他应用带来阻塞,

这样的阻塞,就像我们的thread中的阻塞是类似的,就是你想做一件事,却发现你前面的人在做一件无用的事情,就像你在开车时遇到红灯,你在等红灯的过程中,发现你前面的车主,对,你可以骂他,为啥,他不仅开的是手动档,而且为了省油还熄火了了,你说你气不气人?难道大家停车都要把火给熄灭了?

所以1.1就想了个办法,让大家的请求,等服务器处理完后,不会自动释放,等待客户端来的请求,等客户端的继续的请求,除非客户端请求过来说,服务器大哥,你把连接关了吧!或者服务器上提前设定好一个超时关闭连接的动作,这样,就可以保证,在频繁请求的时候,不需要重复建立连接,这才是1.1的内涵

1.2 这个我也不是很懂,对于Digest和Basic还有一些认识上的偏差,后续会做详细介绍,敬请期待

2.0这个主要是针对1.1作了重构,优化,后期介绍

详细可以参照:https://www.zhihu.com/question/34074946

思考2.0为何要优化?那优化的方向是什么呢?1.0到1.1,是解决了建立连接的复用问题,达到了一次连接,始终有效的效果,那建立连接后,是不是有多次请求,多次请求的一般格式是什么样的?

 

关于1.0 1.1 2.0头部大小写的区别

记住:1.0/1是case-insensitive,啥意思?就是大小写不区分,不敏感,比如,请求header是小写,服务以大写识别,都是可匹配的(contexnt-type和Content-type)

然而,2.0是区分大小写的,就是,发送大写,识别大写,发送小写,识别也必须为小写识别,否则就识别不了了,问题来了,为什么要这样的怪癖,因为:某些浏览器,例如IE(我不确定一定是IE,但IE的印象给我一直不太好),他们喜欢将Content-type转化为content-type,就这么样转换,对方的服务端就无法正确识别content-type了,他不知道content-type就是Content-type,所以这样,就使得客户端和服务端不能通信了,

posted @ 2020-04-14 14:20  菊次郎的幻想  阅读(376)  评论(0编辑  收藏  举报

begin