android TCP客戶端例項
阿新 • • 發佈:2019-02-16
前言:將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(); } } }