Android中使用BufferedReader.readline阻塞读取不到数据,但是ready返回true
通过socket测试工具在电脑上发送消息,Android真机可以收到响应BufferedReader.ready()返回true,但是readline却一直阻塞。
原因:readline()只有在遇到换行符的时候才会结束,因为发消息的时候加一个换行符即可。
测试工具下载地址:http://files.cnblogs.com/files/feijian/SocketTool.rar
附上我的socket客户端代码:
public class QpushClient implements Runnable {
    protected static QpushClient mInstance;
    protected Handler mHandler;
    protected InetSocketAddress mAddress;
    protected String TAG = "QpushClient";
    private final int TIME_OUT = 5 * 1000;
    //巡检周期
    private final int CHECK_PERIOD = 2 * 1000;
    //连接尝试间隔时间
    private final int CONNECT_PERIOD = 30 * 1000;
    private final int HEARTBEART_PERIOD = 10 * 1000;
    //若连接失败或响应失败,则尝试次数为9,若仍无效,则不再尝试
    private final int CONNECT_TRY_TIMES = 9;
    //连接尝试次数
    private int mConnectCount;
    Socket mClientSocket;
    String mHost;
    int mPort;
    //设置是否去读取数据
    boolean isStartRecieveMsg = false;
    //开启心跳检测
    boolean isKeepHeartBeat = false;
    private QpushClient(Handler handler) {
        mHandler = handler;
    }
    public static QpushClient getInstance(Handler handler) {
        if (mInstance == null) {
            mInstance = new QpushClient(handler);
        }
        return mInstance;
    }
    public void init(String host, int port) {
        mHost = host;
        mPort = port;
        new Thread(this).start();
        isStartRecieveMsg = true;
        isKeepHeartBeat = true;
    }
    @Override
    public void run() {
        mAddress = new InetSocketAddress(mHost, mPort);
        if (mClientSocket == null) {
            mClientSocket = new Socket();
        }
        //尝试连接,若未连接,则设置尝试次数
        while (!mClientSocket.isConnected() && mConnectCount < CONNECT_TRY_TIMES) {
            connect();
            if (!mClientSocket.isConnected()) {
                mConnectCount++;
                sleep(CONNECT_PERIOD);
            } else {
                mConnectCount = 0;//连接上,则恢复置0
            }
        }
        if (mClientSocket.isConnected()) {
            //开始登陆
            sendMsg("login");
            recvMsg();
            keepHeartBeat();
        }
    }
    private void connect() {
        try {
            mClientSocket.connect(mAddress);
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "mClientSocket.connect fail " + e.getMessage());
        }
    }
    /**
     * 心跳维护
     */
    private void keepHeartBeat() {
        //设置心跳频率,启动心跳
        while(isKeepHeartBeat){
            sendMsg("我是心跳包");
            sleep(HEARTBEART_PERIOD);
        }
    }
    BufferedWriter mWriter;
    BufferedReader mReader;
    /**
     * 不断的检测是否有服务器推送的数据过来
     */
    public void recvMsg() {
        while (mClientSocket != null && mClientSocket.isConnected() && !mClientSocket.isClosed()) {
            try {
                mReader = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream(), "utf-8"));
                while (isStartRecieveMsg) {
                    Log.e(TAG, "recvMsg5");
                    if (mReader.ready()) {
                        Log.e(TAG, "recvMsg6");
                            /*读取一行字符串,读取的内容来自于客户机
                            reader.readLine()方法是一个阻塞方法,
                            从调用这个方法开始,该线程会一直处于阻塞状态,
                            直到接收到新的消息,代码才会往下走*/
                        String data = mReader.readLine();
                        Log.e(TAG,"isStartRecieveMsg data="+data);
                        //handler发送消息,在handleMessage()方法中接收
                        handlerMsg(data);
                    }
                    Thread.sleep(200);
                }
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            sleep(200);
        }
        if (!mClientSocket.isConnected()) {
            connect();
            recvMsg();
        }
        sleep(CHECK_PERIOD);
    }
    private void sleep(long sleepTime) {
        try {
            Thread.sleep(sleepTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    /**
     * 销毁socket
     */
    public void onDestory() {
        if (mClientSocket != null) {
            try {
                mClientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            mClientSocket = null;
        }
    }
    public void sendMsg(String message) {
        PrintWriter writer;
        try {
            writer = new PrintWriter(new OutputStreamWriter(
                    mClientSocket.getOutputStream()), true);
            writer.println(message);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /*
     * Ready for use.
     */
    public void close() {
        try {
            if (mClientSocket != null && !mClientSocket.isClosed())
                mClientSocket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /**
     * 处理服务器返回过来的消息
     * @param data
     */
    private void handlerMsg(String data){
        //对数据进行protobuf解析
        //消息类型:1=登录成功、2=心跳检测、3=推送消息
        int msgType=1;
        switch(msgType){
            case 1:
                sendMsg("success");
                break;
            case 2:
                sendMsg("success");
                break;
            case 3: //需要通知service
                sendMsg("success");
                mHandler.obtainMessage(QpushService.PUSH_TYPE_DATA, data).sendToTarget();
                break;
        }
    }
}
Android中使用BufferedReader.readline阻塞读取不到数据,但是ready返回true的更多相关文章
- mono for android中使用dapper或petapoco对sqlite进行数据操作
		在mono for android中使用dapper或petapoco,很简单,新建android 类库项目,直接把原来的文件复制过来,对Connection连接报错部分进行注释和修改就可以运行了.( ... 
- 在Android中调用KSOAP2库访问webservice服务出现的服务端返回AnyType{}
		最近在做毕业设计的时候,涉及到了安卓端访问web service服务端数据库,并返回一个值,当我把web service测试通过后,想写一个简单的安卓测试程序,来实现服务端数据库访问,通过web se ... 
- 解决Android中AsyncTask的多线程阻塞问题
		Android开发中执行耗时操作并更新UI时,通常有三种方式:1.直接调用runOnUiThread(new Runnable(){}),使用简单,但不能在Activity之外的环境使用,如View. ... 
- 在android中,如何去掉webview读取网页后点击网页上的按钮出现的方框
		参考:http://blog.sina.com.cn/s/blog_64056edc0100xt3l.html <style type="text/css"> .bor ... 
- Android 中如何获取 H5 保存在 LocalStorage 的数据
		主要分三步: 写个接口,接收 Js 回调 添加到 WebView 主动调用 Js 获取 比如我要获取保存在 LocalStorage 中的 userKey 字段: 1.写个接口,接收 Js 回调 pu ... 
- Android中Service通信(一)——启动Service并传递数据
		启动Service并传递数据的小实例(通过外界与服务进行通信): 1.activity_main.xml: <EditText android:layout_width="match_ ... 
- iview 中table列 一列显示多个数据(后台返回数组显示在列内)
		一.首先出现的是比较复杂的一种情况(多个key) 1.首先页面显示效果如下 2.后台返回数据格式如下: 3.在iview中table的columns中的render函数: 4.具体代码 render: ... 
- java编写socket使用bufferedReader.readLine()问题研究
		不写java代码好久,临时写个socket通讯竟然失败,郁闷之下仔细研究了下. 客户端使用BufferedReader来读取数据,在while中调用BufferedReader.readLine()函 ... 
- Android中ListView控件的使用
		Android中ListView控件的使用 ListView展示数据的原理 在Android中,其实ListView就相当于web中的jsp,Adapter是适配器,它就相当于web中的Servlet ... 
随机推荐
- Shell脚本笔记(一)一些零碎的基础知识
			一些零碎的基础知识 一.认识Shell脚本 一)相关概念 Shell是一种命令解释器,作用是按次序执行(遇到子脚本,先执行子脚本的命令)用户输入的命令和程序. Shell脚本语言是弱类型语言,与其他脚 ... 
- How to show color in CSS
			转至:https://blog.csdn.net/CallMeQiuqiuqiu/article/details/54743459 http://www.w3school.com.cn/cssref/ ... 
- 潭州课堂25班:Ph201805201 django 项目 第十八课 前台 注解 (课堂笔记)
			在静态文件 js/user上当下,的 auth.js 文件中 $(function () { let $username = $('#user_name'); // 选择id为user_name的网页 ... 
- 在C#中,Json的序列化和反序列化的几种方式总结 转载
			转载自 https://www.cnblogs.com/caofangsheng/p/5687994.html 谢谢 在这篇文章中,我们将会学到如何使用C#,来序列化对象成为Json格式的数据 ... 
- /etc/security/limits.conf 文件说明
			/etc/security/limits.conf 是 Linux 资源使用配置文件,用来限制用户对系统资源的使用 语法:<domain> <type> <item& ... 
- jmeter接口测试实例1-添加学生信息
			jmeter实例1:添加学生信息 进入jmeter,添加线程组改名称为添加学生信息(为了好区分接口),添加http请求,输入IP,方法,路径,在body data中输入json串,同上面postman ... 
- javascript 回调函数定义 模板
			函数定义: function callfun(in_param,callback) { console.log(in_param); var out_param='bbbbb'; return (ty ... 
- Git删除本地分支和远程分支
			https://blog.csdn.net/sub_lele/article/details/52289996 git branch help λ git branch -h usage: git b ... 
- Java 基础【19】代理
			Java 代理(Proxy)模式与现实中的代理含义一致,如旅游代理.明星的经纪人. 在目标对象实现基础上,增加额外的功能操作,由此来扩展目标对象的功能. JavaWeb 中最常见的过滤器.Struts ... 
- 微信SDK登录无法调起,微信SDK无法接收回调的几种解决办法
			今天有位同事请求帮忙调试微信登录问题,他遇到了以下2个问题,所以,写篇日志备忘,如果有其它朋友遇到此类问题,都可以照此解决! 平时在开发中,有些开发者经常会遇到微信登录SDK登录时,无法调起微信客户端 ... 
