socket inputstream read

我们在写输入输出流中经常是以循环读取到-1作为结束符。

这个在文件的读写中,是没有问题的,很显然文件有结束符。

这个在socket通讯中,是有问题的,socket.getInputStream().read(buffer)这个函数,会处于阻塞状态,继续等待对方发数据过来。显然不可能中断,即使发一个-1,read也会把-1当作一个值读出来,循环仍将继续。

网上有一个解决方法:利用socket.setSoTimeout(),在第一次读取数据后,超过指定的时间,将发生异常,这时候,捕获异常,使程序继续进行。

我一个同事这样处理:利用inputStream.available(),来判断inputStream中是否还有可读取的值,如果没有,则跳出循环。

这两种做法都有弊端。

第一种做法,本生逻辑上就不合正常的思维,一般来说,我们是要避免抛异常的,这样做会使得程序写起来很别扭,理解起来也相对困难。另外,我们一般是通过传InputStream作为参数的,如private byte[] getEncodedData(InputStream is),这个时候,就必须传sokcet作为参数,不合逻辑。其它的就不再说了。

第二种做法:根据jdk提供的文档,Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. 这句话说明,这个available值不可靠。

后来,也是网上的朋友有仔细思考过这个问题,我仔细查看socket函数,可利用socket.shutdownOutput(),可以很好的解决这个问题。此函数可以,禁用此套接字的输出流。对于 TCP 套接字,任何以前写入的数据都将被发送,并且后跟 TCP 的正常连接终止序列。 如果在套接字上调用 shutdownOutput() 后写入套接字输出流,则该流将抛出 IOException。

后来我仔细想了想。

这种通用问题,别人应该也碰过,应该有已经解决的方法,不过我在google和baidu上找了好多网页,才发现这个提示,而这个提示的来源,还是国外的,呵呵。另外既然是通用问题,写socket类的人是否已经意识到,并提供解决方案呢,这显然已经得到印证。

下面是关键代码,已经测试通过,因为是项目中代码,没法给全代码,想实现的同学,自己补充完善,网上很多,自己写也不难。

服务端:

/**
     * 此方法用于从输入流中获取数据
     *
     * @param is 接收来自客户端socket对应的输入流
     * @return 返回endodedData
     * @throws IOException 抛出的异常,统一在run函数处理
     */
    private byte[] getEncodedData(InputStream is) throws IOException {
        byte[] maxBuffer = new byte[1024 * 64];
        int length = 0;
        int lengthTemp = 0;
        while (-1 != (lengthTemp = is.read(maxBuffer))) { // read方法并不保证一次能读取1024*64个字节
            length += lengthTemp;
            if (length >= 1024 * 64) {
                logger.debug("读入的数据超过1024 * 64");
                break;
            }
        }

        byte[] endodedData = new byte[length];
        System.arraycopy(maxBuffer, 0, endodedData, 0, length);

        logger.info("receiveData:" + DataUtil.bytesToHexString(endodedData) + '\n');
        return endodedData;
    }


客户端:

......

os.write(encodedData);

os.flush();
socket.shutdownOutput();

......

参考资料:

java Socket InputStream 阻塞 问题 :http://charseller.iteye.com/blog/941350
java InputStream读取数据问题 :http://www.cnblogs.com/MyFavorite/archive/2010/10/19/1855758.html
读取InputStream输入流的例子  :http://xuzw13.blog.163.com/blog/static/103147165201152010224717/

粗浅理解,还望同学们指正。

欢迎阅读相关文章: http://hi.csdn.net/linchengzhi
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值