最近做了一个小型的通讯项目,有一点体会,在这里拿来和大家分享一下:
一:关于Socket的长连接
这个项目中,客户提出了“一次连接,10次交互”的需求,就是说创建一个Socket后,在客户端与服务端完成10次交互前(客户端请求,服务端响应算一次交互),不会被关掉。起初按照这种思路来做Socket的长连接,发现在使用阻塞IO的情况下,如果,在一次交互后不关闭Socket,那么下次客户端虽然可以正常发送请求,但是怎么也读不出服务端的响应信息,因为服务端的输入流被阻塞在上次读取后。如果,每次交互后都关掉Socket,就不符合客户的要求了。于是查资料,说是用异步输入输出流java.nio,于是将其引入项目中,结果发现,异步IO虽然为多个Socket提供了不同的通道,但是对一个Socket而言,依然存在上述问题。于是和客户沟通,客户问一技术牛人,结果得到“Socket长连接指的是服务端将消息往客户端推, 就是在一次连接下,客户端向服务端发多条消息, 服务端一次响应完毕,其间,客户端如果在一定的时间内没有消息发往服务端,服务端会主动断开连接”。
二:关于Socket使用中读取响应消息的方法
使用Socket进行通信会涉及到读取服务端的响应消息。读取的方法可分为2类三种。
类1:一次性全部读取。
代码:
方法一:public String getResultStr(Socket sourceSocket)
{
String resultStr = null;
InputStream in;
try {
in = sourceSocket.getInputStream();
int readIndex = 5 * 1024 * 1024;
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(in), readIndex);
char[] charArray = new char[readIndex];
int read_rst = bufferedReader.read(charArray);
resultStr = new String(charArray, 0, read_rst);
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
return resultStr;
}
类2:非一次性读取
方法二:一行行读
public String getResultStr(Socket sourceSocket)
{
String resultStr = null;
InputStream in;
try {
in = sourceSocket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(in));
StringBuffer responseBuffer = new StringBuffer();
String line = bufferedReader.readLine();
while (null != line)
{
responseBuffer.append(line);
line = bufferedReader.readLine();
}
bufferedReader.close();
resultStr = responseBuffer.toString();
} catch (IOException e) {
e.printStackTrace();
}
return resultStr;
}
方法三:一字节一字节读
public String getResultStr(Socket sourceSocket)
{
String resultStr = null;
InputStream in = null;
try {
in = sourceSocket.getInputStream();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(in));
int read_rst = bufferedReader.read();
StringBuffer readBuffer = new StringBuffer();
while (-1 != read_rst)
{
char singleChar = (char) read_rst;
readBuffer.append(singleChar);
}
bufferedReader.close();
resultStr = readBuffer.toString();
} catch (IOException e) {
e.printStackTrace();
}
return resultStr;
}
其中方法一的优点是读取速度快,且不用被超时所扰。缺陷是,只能读取一定量的字节,虽然BufferedReader的构造方法提供了设置缓冲区大小的功能,但是不管设多大,都只能读取一定量的字节,据项目中的情况来看,是65536个。如果响应消息有几MB的话,这种方法是肯定不行的。但是如果读取的消息很小,在65536个字节以内,则可以使用。
方法二的优点是便于做读取后的算法操作,速度嘛也挺快。缺陷是不能精确读取。因为readLine的方法读不出’\n’,’\r\n’,所以读出来的内容其长度与实际长度有出入。
方法三是最优解。(以上只是三种方法的原型,具体业务还要具体实现)
三:关于解决Socket读取响应消息超时的分析及解决方法:
分析
在使用Socket的过程中会遇到读取响应消息超时的问题,这是为什么呢?就我现在的理解,一句话:在服务端还没有关闭连接前,客户端读取响应消息就会一直等待,直到超时。
解决方法:
1.Socket提供的setSoTimeout(int timeout) 方法
在获得Socket的实例后,设置下超时时间,然后当read或是readLine完最后一个字节或是字符串后,会抛一个InterruptedIOException,在catch里做你想做的事情,或break,或关掉连接。
2.如果服务端也是你设计的话(就是响应消息也是你拼接的),请看。
可以在服务端里拼接响应消息的方法里为响应消息加上一个‘\r\n‘,注意一定要加在消息末尾。然后用“二:关于Socket使用中读取响应消息的方法”里第三种方法来读取响应消息,注意,通信消息头中肯定会有“Content-Length“一项,先取出其值(Content-Length表示消息主体的字节长度),接着找出主体消息的起始位置(主体消息中的最前方一定要是个固定的内容),开始计算响应消息的实际字节长度,最后将取出的Content-Length的值与实际计算出的长度进行比较,如果相等就break掉,这样,就不会读到会引起超时消息末尾。
其方法1的优点时易于实现,缺陷是不安定因素太大。setSoTimeout里总要设个值,设多少呢?假设在网络正常情况下读一个1MB的响应消息需要1s,那么如果网络阻塞呢?如果你设一个很大的值,就会影响使用。
方法2的优点是不受网络因素的影响。缺陷是,如果服务端的中文字符编码与流中的中文字符编码不一致,会导致乱码,进而会影响计算的准确度。一旦计算的不准,就会超时。
不过,方法2仍是最优解。
以上就是自己对这个项目的一点体会,欢迎大家指正。
分享到:
相关推荐
软件项目管理学习心得(精选5篇)参考.doc是软件项目管理的学习心得,涵盖了项目管理的基本概念、项目集成管理、项目范围管理、项目进度管理、项目成本管理、项目质量管理、项目人力资源管理、沟通管理、风险管理和...
在Java项目开发中,开发心得主要集中在以下几个方面: 1. **知识技术储备**:开发者需要具备广泛的知识技术,包括但不限于Java基础知识、JSP、数据库管理、Servlet、EJB(Enterprise JavaBeans)、开发环境配置和...
在 Winform 项目中,登录界面验证成功后需要进入主界面,这可以通过在登录窗体中增加一个静态变量来实现。当登录成功时,将静态变量设置为 true,并关闭登录窗体,然后在程序的 Main 入口中使用 Application.Run() ...
【标题】:“推荐一个毕业项目及写作心得” 在信息技术领域,毕业项目是学生们展示自己学习成果和实践能力的重要环节。这个标题所暗示的知识点主要涵盖了毕业设计的选择、实施过程以及项目报告的撰写技巧。 首先,...
项目经理心得体会参考.doc
在IT行业中,项目管理是一项至关重要的技能,它涵盖了多个领域,包括团队协调、计划制定、风险管理以及执行与监督。以下是对标题、描述和标签中所提及的文件内容的详细解析: 1. **产品部、项目组、实施组的关系**...
在IT行业中,项目管理是一项至关重要的技能,它涵盖了项目的规划、执行、监控和收尾等多个阶段,确保项目能够按时、按预算、按质量地完成。本资料合集围绕"IT项目管理心得体会与学习合集"的主题,提供了丰富的学习...
这个"SSH项目源码及心得体会"的资源对于初学者来说尤其宝贵,因为它不仅包含了实际项目的源代码,还记录了开发者在整合和使用SSH框架过程中的心得与经验。 Struts2是MVC(Model-View-Controller)架构模式的一种...
本人做项目经理工作多年,感到做这个工作最要紧的就是要明白什么是因地制宜、因势利导,只有最合适的,没有什么叫对的,什么叫错的,项目经理最忌讳的就是完美主义倾向,尤其是做技术人员出身的,喜欢寻找标准答案,...
看门狗是一个重要的安全机制,它可以作为定时器触发中断或者在程序出现故障时强制系统复位,防止程序失控。在设置看门狗时,需要根据实际需求配置其计时周期。 系统时钟初始化涉及多个寄存器,例如LOCKTIME、PLLCON...
在IT行业中,项目总结与项目心得体会是至关重要的环节,它们能帮助我们提炼经验,提升技能,为未来的项目提供宝贵借鉴。以下将详细讨论这些文件所涵盖的知识点。 首先,我们看到"Ext3.2中文API(最终完成版2010-12-...
### Java开发三年项目经验心得分析 #### 一、项目经验概览 在这篇文章中,作者回顾了自己在Java开发领域三年的工作经历,期间参与了三个不同的项目,从中获得了丰富的实战经验和技术积累。这三个项目分别是涉密...
"项目心得体会.rar"这个压缩包文件,显然包含了某个人或团队在完成一个项目后总结的心得体会,这通常是一份珍贵的文档,记录了他们在项目实施过程中的学习、挑战以及解决策略。下面,我们将深入探讨项目管理的一些...
项目经理应该认识到,计划发布日期只是一个目标,而实际合理发布日期是项目组可以实际实现的日期。 2. 随着项目的进行,实际合理发布日期会逐渐明朗。项目经理应该调整项目计划,使之与实际合理发布日期相符。 3. ...
1. **面向对象编程**:Java是一种纯面向对象的语言,我在项目中深入了解了类、对象、继承、封装和多态等概念。通过创建实体类来模拟现实世界中的对象,我学会了如何设计合理的类结构,以及如何利用多态性提高代码的...
junit测试的一点心得,在spring中加载外部配置文件是的一点小技巧junit测试