java如何实现Socket的长连接和短连接

讨论Socket必讨论长连接和短连接

一、长连接和短连接的概念

  1、长连接与短连接的概念:前者是整个通讯过程,客户端和服务端只用一个Socket对象,长期保持Socket的连接;后者是每次请求,都新建一个Socket,处理完一个请求就直接关闭掉Socket。所以,其实区分长短连接就是:整个客户和服务端的通讯过程是利用一个Socket还是多个Socket进行的。

  可能你会想:这还不简单,长连接不就是不关Socket嘛,短连接不就是每次都关Socket每次都new Socket嘛。然而事实其实并没有那么简单的,请继续看下面的整理

  2、关闭流而保持Socket正常?

    在网上百度了一下,发现很多人都是以关闭流还是关闭Socket来区分长连接和短连接的,其实,个人感觉这种区分方法并没有什么意义:因为这里面有一个事实是,流关闭之后,便不能进行消息的发送(对应关闭输出流)或者接受(对应关闭输入流),因为其实关闭了对应的流,对应连接也就关闭了(这里所说的连接是发送消息的通道!),所以,流关闭而保持Socket开启,是没有达到长连接的效果,贴上测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//发送核心方法
    public String send(String send) throws IOException {
        String rtn = null;
        BufferedWriter writer = null;
        OutputStreamWriter ow = null;
        OutputStream os = null;
        try{
            os = socket.getOutputStream();
            ow = new OutputStreamWriter(os);
            writer = new BufferedWriter(ow);
            char [] sendChar = send.toCharArray();
            ArrayList<Integer> list = new ArrayList<Integer>();
            for(char ch:sendChar){
                list.add((int)ch);
            }
            //进行加密操作
            list = encry(list);
            Iterator<Integer> it = list.iterator();
            while(it.hasNext()){
                writer.write(it.next());
            }
            writer.flush();
            rtn = "发送成功!";
        }finally{
            //注意:直接关闭流将会导致socket关闭,只能通过shutdownOutput/input的方式关闭流
            //另外,流关闭之后,相当于关闭底层的连接,除非新new个socket,否则和客户端的连接相当于断开
//          if(writer!=null){
//              writer.close();
//          }
//          if(ow!=null){
//              ow.close();
//          }
//          if(os!=null){
                //os.close();
//          }
            //socket.shutdownOutput();流关闭之后,相当于关闭底层的连接,除非新<br>new个socket,否则和客户端的连接相当于断开
        }
        return rtn;
    }

  这是我写的一个测试的发送消息的核心方法,在关闭了对应的流(无论是输出或者输入)之后,下一次调用getInputStream或者getOutputStream会抛出异常说:Socket is closed;这里讲明一个事实:Socket和流联系着,流关闭了,Socket其实也就相当于关闭状态!

  其实这个也很好理解,Socket本来就是依靠流进行关闭的,流,就只有一个,你关闭了流,Socket赖以通讯的渠道也就关闭了,与客户的连接也断开了,所以抛出异常是很合理的。

  所以,流关闭而要求Socket正常通讯是不可能的!

  所以,如何实现长连接?

二、长连接的正确实现方式

  1、不关闭流实现长连接?

    前面讨论了,流关闭了而不关闭Socket,还是无法达到长连接的效果的,所以,要长连接,流必须不能关闭!那么,是不是直接不关闭流,然后每次要发消息就直接往流里面任进去数据,然后调用flush()方法强制刷新就行了?其实不行的,这样客户端是无法正常接收信息的,你会发觉就算服务端flush了,客户端还是会一直在read方法那里阻塞!具体原因各位可以看一下java api文档的截图:

 

 文档说明了,如果流一直可用,而且没有读到流的末尾(就是对应着对方流已经关闭或者网络断开!),read会一直阻塞!其实这样做也是可以解释清楚的:本来服务端的read方法就不知道Server端的消息什么时候发送完,说不定我以为数据发送完 了,但其实是因为网络延迟而导致部分数据延后到来(况且也不可能所有数据同时到达),所以,read方法只能一直在阻塞等待对方的应答。所以,怎么实现长连接?

  2、实现长连接的方法

  A、客户端自动退出开读取的动作。前面说了,就算服务端调用了flush方法进行输出刷新,客户端也不一定能退出read的动作,所以还是会阻塞。所以,退出动作必须有客户端程序自己完成,我们可以在服务端没发送完一段消息并且刷新前就进行一个写入结束符号的标志,客户端解析到结束符号时,变可直接退出read的循环读取操作,避免一直阻塞。

  B、可以调用有读取一定字节到某个数组的read方法(不过好像这个不太行,毕竟每次消息的长度好像会变的),当然,这只是针对消息定长的情况。

  下面贴上长连接实现后的代码(其实就是比前面的代码加多了读入结束标记符号)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//发送核心方法
    public String send(String send) throws IOException {
        String rtn = null;
        BufferedWriter writer = null;
        OutputStreamWriter ow = null;
        OutputStream os = null;
        try{
            os = socket.getOutputStream();
            ow = new OutputStreamWriter(os);
            writer = new BufferedWriter(ow);
            char [] sendChar = send.toCharArray();
            ArrayList<Integer> list = new ArrayList<Integer>();
            for(char ch:sendChar){
                list.add((int)ch);
            }
            //进行加密操作
            list = encry(list);
            Iterator<Integer> it = list.iterator();
            while(it.hasNext()){
                writer.write(it.next());
            }
            //写入结束标志符号:%
            writer.write('%');
            writer.flush();
            rtn = "发送成功!";
        }finally{
            //注意:直接关闭流将会导致socket关闭,只能通过shutdownOutput/input的方式关闭流
            //另外,流关闭之后,相当于关闭底层的连接,除非新new个socket,否则和客户端的连接相当于断开
//          if(writer!=null){
//              writer.close();
//          }
//          if(ow!=null){
//              ow.close();
//          }
//          if(os!=null){
                //os.close();
//          }
            //socket.shutdownOutput();流关闭之后,相当于关闭底层的连接,除非新new个socket,否则和客户端的连接相当于断开
        }
        return rtn;
    }

 三、短连接

    短连接就基本没什么好讲的啦,只是每次关闭Socket和流时需要注意一下事情:

    1、虽然前面说了流关闭了,Socket就不可用了,但是,我们还是要显式的关闭Socket的,因为在Socekt中还有中状态:叫做半连接状态,当我们只是用到输出流的时候,我们关闭了输出流,并且不能直接调用close方法,只能调用shutDown对应方法(具体请查看java API),其实输入流还是连接着的(只是我们没有用到而已!),这时候,如果没有显式关闭Soceket,很容易导致内存泄露,所以,所有流Socket都要显式关闭

    2、短连接和长连接有不同的用途:对于某次服务只需要一次回话的客户,使用短连接显得简单;但是,如果该次服务需要很多交互式的操作通信,那还是长连接比较高性能,毕竟,Socket的打开和关闭都是很耗性能的。

 

四、总结

  1、对应流关闭,Socket的对应输入(出)数据的通道也就关闭,此时无法达到长连接效果;

  2、关闭Socket,记得显式关闭流与socket,顺序是线管流再关socket.

  3、要实先长连接,一般需要发送结束标记符号来告诉客户端服务端的某段消息已经发送完毕,否则客户端会一直阻塞在read方法。

 

原文转载:https://www.cnblogs.com/lcplcpjava/p/6581179.html

 

转载于:https://www.cnblogs.com/AndyAo/p/8232700.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/267782.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

疯狂的java 目录_疯狂创客圈 JAVA 高并发 总目录

无编程不创客&#xff0c;疯狂创客圈&#xff0c;一大波编程高手正在交流、学习中!疯狂创客圈&#xff1a; JAVA 高并发 研习社群&#xff0c; QQ群&#xff1a;104131248(已满) 236263776 (请加此群)疯狂创客圈 经典图书 &#xff1a; 《Netty Zookeeper Redis 高并发实战…

也谈云计算

云计算的介绍和讨论不时见诸于报章网端&#xff0c;但是基本上是各说各话&#xff0c;众说纷纭中让大家仍然感觉云里雾里&#xff0c;不见明路。 本文没有涵盖全部的观点&#xff0c;但却希望提供一种思路&#xff0c;大家共同探讨云的建设。云计算是英文Cloud Computing的翻译…

用phpmyadmin更改root密码的方法

首先用root账号登陆phpmyadmin&#xff0c;然后点击左侧进入mysql数据库&#xff0c;在顶部点击“mysql”进入sql输入界面。输入以下命令&#xff1a; update user set passwordpassword(root) where Userroot root为你希望修改的密码&#xff0c;切记不要在数据库中直接手工修…

Android开发 ---多线程操作:Handler对象,消息队列,异步任务下载

效果图&#xff1a; 1、activity_main.xml 描述&#xff1a;定义了六个按钮 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:id"id/activity_main&quo…

Lunx运维监控_shark巨菜_基础篇

Lunx运维监控_shark巨菜_基础篇一、监控重要性单单从“监控”两个字来谈&#xff0c;范围之广可以涵盖我们生活的方方面面&#xff0c;我们生活和工作中处处可见视频监控的摄像机&#xff1b;机房中的电压电流监控、干湿计、温度计&#xff1b;值班室的网络监控&#xff0c;网站…

java项目皮肤包_java swing项目皮肤包+使用方法说明

这是java swing项目皮肤包使用方法说明下载&#xff0c;项目可用的皮肤包&#xff0c;总共四个&#xff0c;自己下载总结的&#xff0c;包含使用代码说明。直接在main函数最开始加入说明代码即可使用~~~加入代码后记得处理异常&#xff01;软件介绍java swing项目皮肤包使用方法…

WinXP的EFS加密文件如何解密?

根据网上流传的资料&#xff0c;EFS&#xff08;Encrypting File System&#xff09;EFS加密是基于公钥策略的。在使用EFS加密一个文件或文件夹时&#xff0c;系统首先会生成一个由伪随机数组成的FEK(File Encryption Key&#xff0c;文件加密钥匙)&#xff0c;然后将利用FEK和…

关于滚动条出现页面跳动问题

二、CSS3计算calc和vw单位巧妙实现滚动条出现页面不跳动 很简单&#xff0c;只要一行代码就搞定了&#xff1a; .wrap-outer {margin-left: calc(100vw - 100%); } 或者&#xff1a; .wrap-outer {padding-left: calc(100vw - 100%); } 然后就可以庆祝放鞭炮啦&#xff01;&…

17款漂亮的 HTML5 网站模板免费下载

在过去的几年&#xff0c;设计师们已开始关注和使用 HTML5 了&#xff0c;如今 HTML5 得到了更加广泛的应用。今天&#xff0c;本文与大家分享17款免费的 HTML5 网站模板&#xff0c;看看有没自己喜欢的。 1- Smart Net 免费下载 2- Photo Art 免费下载 3- The Art Of Business…

java动态生成sdk_android、java制作sdk以及自动生成文档

最近一直在做android开发&#xff0c;昨天经理让我写个接口SDK做个接口文档&#xff0c;以便后面的开发。这让我很焦灼&#xff0c;SDK怎么做&#xff1f;要是只有敲代码还好。可是那个接口文档&#xff01;&#xff01;&#xff01;文档这东西最讨厌了&#xff0c;头都大了后来…

利用 Selenium 自动化 web 测试

Selenium 是一个健壮的工具集合&#xff0c;跨很多平台支持针对基于 web 的应用程序的测试自动化的敏捷开发。它是一个开源的、轻量级的自动化工具&#xff0c;很容易集成到各种项目中&#xff0c;支持多种编程语言&#xff0c;比如 .NET、Perl、Python、Ruby 和 Java™ 编程语…

乌班图 之 常用操作命令(二)

一、tree命令 tree [目录名]  以树状图列出文件目录 -d 只显示目录&#xff0c;不显示文件。 二、cp命令 cp即copy   cp 源文件 目标文件 -i  重名自动 覆盖 加了 -i 提示   y/n -r  复制目录及该目录下所有字目录和文件&#xff0c;目标文件必须是一个目录名。 三、…

Exchange2010外部传输域的使用方法

安装好EX2010后并不能马上与外部邮件进行收发&#xff0c;需要进行以下几个配置&#xff1a; 1、配置接收连接器 2、配置接受域 3、配置发送连接器 可以参考这个链接&#xff1a;http://www.chinaemail.com.cn/server/xtfl/Exchange/201101/59114.html 下面以我的实例来说明一…

Shiro安全框架入门篇

一、Shiro框架介绍 Apache Shiro是Java的一个安全框架&#xff0c;旨在简化身份验证和授权。Shiro在JavaSE和JavaEE项目中都可以使用。它主要用来处理身份认证&#xff0c;授权&#xff0c;企业会话管理和加密等。Shiro的具体功能点如下&#xff1a; &#xff08;1&#xff09;…

asp.net ajax1.0基础回顾(七):综合应用

本文将通过学生信息管理来介绍asp.net ajax的综合应用实例&#xff0c;包括“浏览”、“查询”、“添加”和“多选删除”功能&#xff0c;以及其它相关设计。 本示例源代码下载地址&#xff1a;http://down.51cto.com/data/220541 本示例中&#xff0c;程序架构参考Petshop&…

ASP.NET MVC3书店--第五节 表单编辑(第二部分)(转)

http://blog.sina.com.cn/s/blog_6ad539a90100r469.html5.5 使用HTML帮助器来截短文字 使用我们的StoreManager控制器中的Index方法添加视图的时候&#xff0c;有一个潜在的问题。事实上&#xff0c;我们的书名与作者名属性的长度值可能超出页面上 所定义的这两个列的长度。我们…

前端“黑话”polyfill

前言 在Web前端开发这个日新月异的时代&#xff0c;总是需要阅读一些最新的英文技术博客来跟上技术的发展的潮流。而有时候会遇到一些比较高频的“黑话”&#xff0c;在社区里面可能已经是人人皆知的“共同语言”&#xff0c;而你接触的少就偏偏看不懂。就像现在几乎所有中国人…

java 什么是线程同步,java多线程同步集合是什么?并发集合是什么?

java中关于集合的内容也是十分丰富的&#xff0c;而且相关的知识点也是十分多的。多线程集合所涵盖的范围是十分广阔的。今天就来为大家介绍一下&#xff0c;java多线程同步集合是什么以及并发集合是什么?一起来看看吧。首先我们需要知道的是&#xff0c;无论是同步集合还是并…

mysql数据库面试总结(一)

1、数据库优化  1&#xff09;数据库范式 第一范式&#xff08;1NF&#xff09;&#xff1a;强调的是列的原子性&#xff0c;即列不能够再分成其他几列。 如电话列可进行拆分---家庭电话、公司电话 第二范式&#xff08;2NF&#xff09;&#xff1a;首先是 1NF&#xff0c;另外…

思科路由器IKEV2 L2L***预共享密码认证最简化配置

一.概述:思科路由器对于IKEV2&#xff0c;是有很多预配的&#xff0c;因此可以很少的配置就能完成IKEV2的配置。二.基本思路&#xff1a;A.两边都用SVTI的方式配置Flex ***B.没有用动态路由&#xff0c;配置静态路由,如果一边用DVTI&#xff0c;则需要两边配置静态路由三.测试拓…