使用socket读取服务器发送的数据问题

刚刚项目使用到socket进行数据的传送,其中数据的读取问题着实
费了老大的劲,以此分享希望能让有缘人少走弯路。

new Thread() {
            @Override
            public void run() {
                try {
                    mSocket = new Socket(SERVICEADD, DST_PORT);
                    //设置socket读取数据流的超时时间
                    mSocket.setSoTimeout(5000);
                    mSocket.setTcpNoDelay(true);
                    //设置客户端close()方法起作用时延时30s关闭socket
                    mSocket.setSoLinger(true, 30);
                    mSocket.setSendBufferSize(4096);
                    //防止服务器端无效时,客户端长时间处于连接状态
                    mSocket.setKeepAlive(true);
                    OutputStream ou = mSocket.getOutputStream();
                    //向服务器发送要查询的数据
                    ou.write(queryContent.getBytes());
                    ou.flush();
                    //读取发来服务器信息
                    BufferedReader br = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
                    List<QueryDatas> queryDatases = QueryFomart.formatSocketString(br);
                    EventBus.getDefault().post(queryDatases);
                    br.close();
                    mSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

对于使用readLine读取数据的一个问题就是,无法走到while后面去,究其原因:

1.误以为readLine()是读取到没有数据时就返回null(因为其它read方法当读到没有数据时返回-1),而实际上readLine()是一个阻塞函数,当没有数据读取时,就一直会阻塞在那,而不是返回null;因为readLine()阻塞后,System.out.println(message)这句根本就不会执行到,所以在接收端就不会有东西输出。要想执行到System.out.println(message),一个办法是发送完数据后就关掉流,这样readLine()结束阻塞状态,而能够得到正确的结果,但显然不能传一行就关一次数据流;另外一个办法是把System.out.println(message)放到while循环体内就可以。

2.readLine()只有在数据流发生异常或者另一端被close()掉时,才会返回null值。

3.如果不指定buffer大小,则readLine()使用的buffer有8192个字符。在达到buffer大小之前,只有遇到”/r”、”/n”、”/r/n”才会返回。

小结,使用readLine()一定要注意:

1、读入的数据要注意有/r或/n或/r/n
2、没有数据时会阻塞,在数据流异常或断开时才会返回null
3、使用socket之类的数据流时,要避免使用readLine(),以免为了等待一个换行/回车符而一直阻塞
4、或者是服务器端在发送完数据就进行关闭

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章