經過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; } } }