Android中使用BufferedReader.readline阻塞讀取不到數據,可是ready返回true

經過socket測試工具在電腦上發送消息,Android真機能夠收到響應BufferedReader.ready()返回true,可是readline卻一直阻塞。服務器

緣由:readline()只有在遇到換行符的時候纔會結束,由於發消息的時候加一個換行符便可。socket

測試工具下載地址:http://files.cnblogs.com/files/feijian/SocketTool.raride

 

附上個人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;

        }
    }
}
相關文章
相關標籤/搜索