Socket多線程接發指令

基礎知識

  • 多線程
  • 消息機制
  • 基於TCP協議的網絡通信

創建多線程的方法

  1. 一種是,繼承Thread類
    Thread類代表線程類,它的兩個最主要的方法是:
    run()——包含線程運行時所執行的代碼
    Start()——用於啓動線程
  2. 另一種是,實現Runnable接口
    實現Runnable接口,讓類實現Runnable接口,然後把run方法單獨提出來

兩種方法的區別:
這裏寫圖片描述

  1. Callable、Future和FutureTask:在執行完線程之後可以返回執行結果
    原文鏈接:http://www.cnblogs.com/dolphin0520/p/3949310.html

handle消息機制

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();
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章