基础知识
- 多线程
- 消息机制
- 基于TCP协议的网络通信
创建多线程的方法
- 一种是,继承Thread类
Thread类代表线程类,它的两个最主要的方法是:
run()——包含线程运行时所执行的代码
Start()——用于启动线程 - 另一种是,实现Runnable接口
实现Runnable接口,让类实现Runnable接口,然后把run方法单独提出来
两种方法的区别:
- Callable、Future和FutureTask:在执行完线程之后可以返回执行结果
原文链接:http://www.cnblogs.com/dolphin0520/p/3949310.html
handle消息机制
- Android 消息处理机制(Looper、Handler、MessageQueue,Message)
原文链接:http://www.jianshu.com/p/02962454adf7 - Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
原文链接:http://blog.csdn.net/lmj623565791/article/details/38377229
Handler类的主要作用:
- 在新启动的线程中发送消息 handler.sendMessage(msg);
- 在主线程中获取、处理消息 public void handleMessage(Message msg)
- 消息的载体Message
基于TCP协议的网络通信
SmartBed上位机控制APP指令传送与接收采用TCP的sokect多线程
/**
* Description:指令传送和接收的线程
* @author zhangjing
*
*/
public class SBClientThread implements Runnable
{
private Context context;
private String IPAddress;
private int ServerPort;
private boolean isRemoterServer;
private Socket s;
// 定义向UI线程发送消息的Handler对象
private Handler handler;
// 定义接收UI线程的消息的Handler对象
public Handler revHandler;
// 该线程所处理的Socket所对应的输入流
InputStream is = null;
// 该线程所处理的Socket所对应的输出流
OutputStream os = null;
/**
* 设备连接构造函数
* @param context
* @param handler
* @param iPString IP地址
* @param portString 端口号
*/
public SBClientThread(Context context, Handler handler,String iPString, String portString)
{
this.context = context;
this.handler = handler;
IPAddress = iPString;
ServerPort = Integer.parseInt(portString);
isRemoterServer = false;
}
/**
* 远程服务器连接构造函数
* @param context
* @param handler
*/
public SBClientThread(Context context, Handler handler){
this.context = context;
this.handler = handler;
IPAddress = "xxxx.xxxx.xxxx.xxxx";//远程服务器2
ServerPort = 8383;
isRemoterServer = true;
}
@Override
public void run() {
// TODO Auto-generated method stub
try
{
//Thread.sleep(1000);//线程暂停一秒
s = new Socket();
SocketAddress endpoint = new InetSocketAddress(IPAddress , ServerPort);
//设置连接超时时间
s.connect(endpoint, 5*1000);
//s = new Socket(IPAddress,ServerPoset);
is = s.getInputStream();
os = s.getOutputStream();
//输出连接信息
if(s.isConnected()){
SBCommand.isConnect = true;
Message msg = new Message();
msg.what = 0x567;
//msg.obj = new String(s+"已连接!");
if(isRemoterServer){
//msg.obj = new String("远程服务器连接成功 !\n\t\t\t\t\t [ "+s.getInetAddress().getHostAddress()+":"+s.getPort()+" ]");
msg.obj = new String("远程服务器连接成功 !");
}else {
msg.obj = new String("设备连接成功 !\n\t\t\t\t\t [ "+s.getInetAddress().getHostAddress()+":"+s.getPort()+" ]");
}
handler.sendMessage(msg);
//提示
handler.post(new Runnable() {
@Override
public void run() {
if(isRemoterServer){
Toast.makeText(context.getApplicationContext(),"远程服务器连接成功",
Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context.getApplicationContext(),"设备连接成功",
Toast.LENGTH_SHORT).show();
}
}
});
}
// 启动一条子线程来读取服务器响应的数据
new Thread()
{
@Override
public void run()
{
try
{
// 每当读到来自服务器的数据之后,发送消息通知程序界面处理该数据
while(true){
int count = 0;
while (count == 0) {
count = is.available();
}
byte[] buffer = new byte[count];
is.read(buffer);
String revString = SBCommand.bytesToHexString(buffer);
//revString =" " + revString;
Message msg = new Message();
msg.what = 0x123;
msg.obj = revString;
handler.sendMessage(msg);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}.start();
// 为当前线程初始化Looper
Looper.prepare();
// 创建revHandler对象
revHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
// 接收到UI线程中用户输入的数据
if (msg.what == 0x345)
{
// 将用户在文本框内输入的内容写入网络
// 接收到UI线程中用户输入的数据
try
{
String commString = null;
commString = msg.obj.toString();
os.write(SBCommand.hexStringToByte(commString));
os.flush();
}
catch (Exception e)
{
e.printStackTrace();
Message msg1 = new Message();
msg1.what = 0x789;
msg1.obj = new String("连接已断开!");
handler.sendMessage(msg1);
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context.getApplicationContext(),"指令发送失败,请重新连接",
Toast.LENGTH_LONG).show();
}
});
}
}
}
};
// 启动Looper
Looper.loop();
}
catch(SocketTimeoutException ex)
{
Message msg = new Message();
msg.what = 0x789;
msg.obj = new String("连接超时!");
handler.sendMessage(msg);
//SBClient.isConnect = false; 放在handler消息队列中 ,以下同理
//提示
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context,"请检查连接信息,重新连接",
Toast.LENGTH_SHORT).show();
}
});
}
catch (Exception e)
{
e.printStackTrace();
Message msg = new Message();
msg.what = 0x789;
msg.obj = new String("连接失败!");
handler.sendMessage(msg);
//SBClient.isConnect = false;
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context.getApplicationContext(),"请检查连接信息,重新连接",
Toast.LENGTH_SHORT).show();
}
});
}
}
/**
* 注销Soket,关闭wifi
*/
public void onDestroy() {
//此程序影响UI线程,故增加新线程
new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
try {
if(s!=null)
{
s.close();
s = null;
is.close();
is = null;
os.close();
os = null;
SBCommand.isConnect = false;
ProgressDialog.closeDialogProgress();
Message msg = new Message();
msg.what = 0x567;
msg.obj = new String("连接关闭成功!");
//注意:Toast在线程中需要消息机制
handler.sendMessage(msg);
//提示
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(context.getApplicationContext(),"设备连接关闭成功",
Toast.LENGTH_SHORT).show();
}
});
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}