• 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;
    
            }
        }
    }
  • 相关阅读:
    Spring——AOP
    Spring——事务管理
    分布式和集群的区别
    数据结构——二叉树
    数据结构——队列
    C语言 一维数组叠加为二维数组样例
    C语言一维数组转换为二维数组
    C语言 二维数组复制、清零及打印显示
    C语言 动态创建二维数组
    java byte【】数组与文件读写(增加新功能)
  • 原文地址:https://www.cnblogs.com/feijian/p/6933832.html
Copyright © 2020-2023  润新知