1. 程式人生 > >android TCP客戶端例項

android TCP客戶端例項

前言:將socket開啟,傳送和接收分開在3個子執行緒,傳送和接收資料互不影響。

1.開啟socket子執行緒

public class StartSocketThread implements Runnable {public static Socket socket;Message msg_main = MainActivity.myhandler.obtainMessage();//////////////
@Override
public void run() {
        try {
            String socket_ip = DeviceMsg.getAddress();
String socket_port = DeviceMsg.getPort
(); if (socket_ip==null || socket_port=="") { return; } int Socket_port = Integer.parseInt(socket_port); socket = new Socket(socket_ip,Socket_port);//連線服務端的IP MainActivity.running = true;//socket執行緒執行中標誌位 if(socket.isConnected()&&!socket.isClosed()){//成功連線socket物件
//啟動接收資料的執行緒 new Thread(new SocketReceiveThread(socket)).start(); //啟動傳送資料的執行緒 new Thread(new SocketSendThread(socket)).start(); //傳送連線成功訊息到主執行緒 msg_main.what=Const.ConnectSuccess; MainActivity.myhandler.sendMessage(msg_main); } }catch (Exception e) { e.printStackTrace(); //利用Handler返回資料(連線失敗)到主執行緒
msg_main.what= Const.ConnectFail; MainActivity.myhandler.sendMessage(msg_main); MainActivity.running = false; Log.e("StartThread:",e.getMessage()); } } }

2. 傳送資料子執行緒

public class SocketSendThread implements Runnable {

    private OutputStream out = null;
    public static boolean writing = false;
//建立建構函式來獲取socket物件的輸入流
public SocketSendThread(Socket socket) throws IOException {
        out = socket.getOutputStream();//得到socket的輸出流
}
    @Override
public void run() {
        // 傳送請求資料
while (MainActivity.running) {
            try {

                while (writing == true) {
                    writing = false;
                    byte[] codeToSend = CodeList.getCodeToSend();
out.write(codeToSend);
String str = new String(codeToSend);
}
                //資料最後加上換行符才可以讓伺服器端的readline()停止阻塞
//                out.write((str).getBytes("utf-8"));} catch (IOException e) {
                e.printStackTrace();
}
        }
    }
}

3. 接收資料子執行緒

public class SocketReceiveThread implements Runnable {

    private InputStream is;
    private String str_receive;
    private String Tag = "SocketReceiveThread";
//建立建構函式來獲取socket物件的輸入流
public SocketReceiveThread(Socket socket) throws IOException {
        is = socket.getInputStream();
}

    @Override
public void run() {
        while (MainActivity.running) {
            InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
//用Handler把讀取到的資訊發到主執行緒
Message msg0 = MainActivity.myhandler.obtainMessage();
            try {
                //讀伺服器端發來的資料,阻塞直到收到結束符\n或\r
//                str_receive = br.readLine();
                //非阻塞接收資料,但限定接收資料位元組
byte buffer[] = new byte[1024*30];
                int count = is.read(buffer);
                if(count != -1){
                    str_receive = new String(buffer,0,count);
}else { MainActivity.running = false;StartSockerThreat.socket.close();return;}

            } catch (NullPointerException e) {
                e.printStackTrace();
Log.e(Tag,e.getMessage());
MainActivity.running = false;//防止伺服器端關閉導致客戶端讀到空指標而導致程式崩潰
msg0.what = Const.ServiceDisconnect;
MainActivity.myhandler.sendMessage(msg0);//傳送資訊通知使用者客戶端已關閉
break;
} catch (IOException e) {
                e.printStackTrace();
                break;
}

//                Message msg0 = MainActivity.myhandler.obtainMessage();
//                msg0.what = 1;//把讀到的內容更新到UI
//                msg0.obj = str_receive;
//                MainActivity.myhandler.sendMessage(msg0);
try {
                Thread.sleep(400);
} catch (InterruptedException e) {
                e.printStackTrace();
Log.e(Tag,e.getMessage());
}

        }

    }
}

4. socket的使用

public class MainActivity extends BaseActivity {

    private String Tag = "MainActivity";
    public static Handler myhandler;
//socket執行緒是否running的標誌位
public static boolean running = false;
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//去除標題
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 設定全屏
setContentView(R.layout.activity_main);
//例項化Handler,用於程序間的通訊//////////////////
myhandler = new MyHandler();
//啟動Socket執行緒
new Thread(new StartSocketThread()).start();
}

  
   

    class MyHandler extends Handler{//在主執行緒處理Handler傳回來的message
@Override
        public void handleMessage(Message msg) {

//            Intent intent = new Intent("com.example.BroadcastReceiver.MY_BROADCAST");
String currentActivityName = ActivityName.getName();
            switch (msg.what) {
                case 1:
                String str = (String) msg.obj;
Log.i("received:",str);
                    break;
                case Const.ConnectSuccess:
                    Log.i("handleMessage_Socket", "連線成功");
Toast.makeText(MyApplication.getContext(),
"連線成功!", Toast.LENGTH_SHORT).show();
                    break;
                case Const.ServiceDisconnect:
                    Log.i("handleMessage_Socket", "服務端連線斷開");
Toast.makeText(MyApplication.getContext(),
"與伺服器斷開連線!", Toast.LENGTH_SHORT).show();
                    break;
                case Const.ConnectFail:
                    Log.i("handleMessage_Socket", "連線失敗");
Toast.makeText(MyApplication.getContext(),
"連線失敗", Toast.LENGTH_LONG).show();
                    break;
                default:
                    break;
}
        }

    }

   
    /**
     * 銷燬activity
     */
@Override
    protected void onDestroy(){
        super.onDestroy();
        if(broadcastReceiver != null){
            unregisterReceiver(broadcastReceiver);//取消註冊廣播
}
        if (StartSocketThread.socket == null) {
            return;
}
        try {
            //關閉Socket執行緒
this.running = false;
StartSocketThread.socket.close();
} catch (NullPointerException | IOException e) {
            e.printStackTrace();
}

    }


}