通过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的更多相关文章

  1. mono for android中使用dapper或petapoco对sqlite进行数据操作

    在mono for android中使用dapper或petapoco,很简单,新建android 类库项目,直接把原来的文件复制过来,对Connection连接报错部分进行注释和修改就可以运行了.( ...

  2. 在Android中调用KSOAP2库访问webservice服务出现的服务端返回AnyType{}

    最近在做毕业设计的时候,涉及到了安卓端访问web service服务端数据库,并返回一个值,当我把web service测试通过后,想写一个简单的安卓测试程序,来实现服务端数据库访问,通过web se ...

  3. 解决Android中AsyncTask的多线程阻塞问题

    Android开发中执行耗时操作并更新UI时,通常有三种方式:1.直接调用runOnUiThread(new Runnable(){}),使用简单,但不能在Activity之外的环境使用,如View. ...

  4. 在android中,如何去掉webview读取网页后点击网页上的按钮出现的方框

    参考:http://blog.sina.com.cn/s/blog_64056edc0100xt3l.html <style type="text/css"> .bor ...

  5. Android 中如何获取 H5 保存在 LocalStorage 的数据

    主要分三步: 写个接口,接收 Js 回调 添加到 WebView 主动调用 Js 获取 比如我要获取保存在 LocalStorage 中的 userKey 字段: 1.写个接口,接收 Js 回调 pu ...

  6. Android中Service通信(一)——启动Service并传递数据

    启动Service并传递数据的小实例(通过外界与服务进行通信): 1.activity_main.xml: <EditText android:layout_width="match_ ...

  7. iview 中table列 一列显示多个数据(后台返回数组显示在列内)

    一.首先出现的是比较复杂的一种情况(多个key) 1.首先页面显示效果如下 2.后台返回数据格式如下: 3.在iview中table的columns中的render函数: 4.具体代码 render: ...

  8. java编写socket使用bufferedReader.readLine()问题研究

    不写java代码好久,临时写个socket通讯竟然失败,郁闷之下仔细研究了下. 客户端使用BufferedReader来读取数据,在while中调用BufferedReader.readLine()函 ...

  9. Android中ListView控件的使用

    Android中ListView控件的使用 ListView展示数据的原理 在Android中,其实ListView就相当于web中的jsp,Adapter是适配器,它就相当于web中的Servlet ...

随机推荐

  1. 安装完最小化 RHEL/CentOS 7 后需要做的 30 件事情7. 安装 PHP PHP 是用于 web 基础服务的服务器端脚本语言。它也经常被用作通用编程语言。在最小化安装的 CentOS 中安

    CentOS 是一个工业标准的 Linux 发行版,是红帽企业版 Linux 的衍生版本.你安装完后马上就可以使用,但是为了更好地使用你的系统,你需要进行一些升级.安装新的软件包.配置特定服务和应用程 ...

  2. 如何绘制UML图?

    首先推荐在线绘制UML的网址:https://www.processon.com/,很好用. 在软件开发过程中,开发人员往往需要通过绘制类图来理清业务的实现思路,从而方便代码实现,也便于后期的代码维护 ...

  3. UltraEdit使用(工具类似于notepad++)

    打开多个文件,在多个文件中切换,鼠标点/ Ctrl+Tab自动换行的设置: 高级-->配置-->编辑器-->自动换行,制表符设置-->默认为每个文件启用自动换行 去掉自动备份设 ...

  4. __c语言__整型、实型的存储(十进制转二进制)

    float 和 double 类型数据在内存中的存储方法 无符号整型采用32位编码,带符号整型数采用1个符号位31位底数编码: 单精度数据采用了1位符号位,8位阶码,23位尾数的编码: 双精度数据采用 ...

  5. 当前线程不在单线程单元中,因此无法实例化 ActiveX 控件“8856f961-340a-11d0-a96“

    在做采集时,有些网页因服务器限制用webclient或者webrequest不能获取html,这时我们可以用webbrowser的方法来绕过对方服务器的限制,但是在实例化webbrowser 的时候发 ...

  6. Win server 2012 +IIS8.0下安装SSL证书

    SSL证书的申请: 成功在景安申请证书后,会得到一个有密码的压缩包文件,输入证书密码后解压得到五个文件:for Apache.for IIS.for Ngnix.for Other Server,这个 ...

  7. springboot上传文件并检查图片大小与格式

    @PostMapping(value = "/uploadDriverImage") public JsonResVo uploadDriverImage(@RequestPara ...

  8. MySQL中exists和in的区别及使用场景

    exists和in的使用方式: 1 #对B查询涉及id,使用索引,故B表效率高,可用大表 -->外小内大 1 select * from A where exists (select * fro ...

  9. HBuilder的扩展插件开发暴露了一个事实:其实不能实现写一次代码实现跨平台App生成

    HBuilder的扩展插件开发,原来并不能生成单独的插件jar,而是以源码 - 类的形式进行开发,这其实就要求必须使用离线打包. 事实上,开发顺序应该是:先弄好离线打包框架,然后在AS里进行扩展插件开 ...

  10. html提交表单到Servlet

    源码地址 https://github.com/YouXianMing/Java-Web-Study/tree/master/Servlet-Form 演示效果(注意post与get提交方式浏览器地址 ...