socket inputstream read bug

咱们在写输入输出流中常常是以循环读取到-1做为结束符。html

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

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

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

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

这两种作法都有弊端。google

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

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

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

后来我仔细想了想。code

这种通用问题,别人应该也碰过,应该有已经解决的方法,不过我在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

相关文章
相关标签/搜索