Socket通过读取数据阻塞的解决方案

写了一个简单的web后台,用socket接收并解析http请求。然而在网页发出第一次请求时总会卡住(其实是流阻塞了),刷新后可以访问。以及总是读取不到最后一部分数据。

刚开始是这样写的

private String getStringFromIOStream(InputStream ios){
        BufferedReader reader = new BufferedReader( new InputStreamReader(ios));
        StringBuilder ret = new StringBuilder();
        String tstr=null;
        while ((tstr=reader.readLine()) != null) {
           ret.append(tstr).append("\n");
           System.out.println(tstr);
        }
        return ret.toString();
}

查看线程信息发现是阻塞在了“tstr=reader.readLine()”这一行。得知是socket输入流读取信息阻塞了,可以理解阻塞在了信息最后一行。于是给socket对象添加超时,并处理异常,如下:

Socket client = tm.serverSocket.accept();
client.setSoTimeout(10); // 这里设置超时时长为10毫秒,对于读取http请求足够了
private String getStringFromIOStream(InputStream ios){
        BufferedReader reader = new BufferedReader( new InputStreamReader(ios));
        StringBuilder ret = new StringBuilder();
        String tstr=null;
        try {
            while ((tstr=reader.readLine()) != null) {
                ret.append(tstr).append("\n");
                System.out.println(tstr);
            }
        }catch (IOException e){ // 读取完成时,超时会报异常,结束阻塞。
         }
        return ret.toString();
}

这是一旦超时便出发异常,从而解决了阻塞的问题。正在感觉完事大吉时,发现接收不到post请求发来的参数,而http请求,post的参数正是数据的最后一行。于是想到应该是http请求最后没有换行,所以readLine()阻塞在了最后一行数据上,而一旦发生异常,最后一行数据就拿不到了。想过添加参数,但发现添加了参数的Http请求,将所有参数封装在了同一行上,解决。于是换思路,考虑使用字节流解析来避免丢失最后一行数据的问题。代码如下

    private String getStringFromIOStream(InputStream ios) {
        int byteArrLen = 128;

        byte[] bytes = new byte[byteArrLen];
        StringBuilder ret = new StringBuilder();
        int len = byteArrLen;
        try{
            while ((len=ios.read(bytes)) != -1 ){ // 当客户端主动中断连接时此处会返回-1
                ret.append(new String(bytes,0,len)); // 在最后一次读取,len会小于数组大小,此处设置len避免末尾无效数据
                System.out.println(new String(bytes,0,len));
                if(len<byteArrLen){   // 获取不到预定大小说明可以结束
                    break;
                }
            }
        }catch (IOException e){ // 超时结束

        }
        return ret.toString();
    }

有4处细节需要注意,都写在上面备注里了。其中三处是结束循环,都不可少。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

horo99

求个赞啦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值