15.Android-實現TCP客戶端,支持讀寫

在上章14.Android-使用sendMessage線程之間通訊咱們學習瞭如何在線程之間發送數據.html

接下來咱們便來學習如何經過socket讀寫TCP.java

須要注意的是socket必須寫在子線程中,不能在ui主線程中直接使用,因此咱們這裏建立了兩個class:android

MainActivity(主界面)、TcpThread(獲取socket接收的數據)服務器

因爲代碼有註釋了,因此就不解釋了.app

1.gif效果以下socket

 

2.activity_main.xml以下所示:tcp

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" >

    
    <EditText android:id="@+id/et_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:hint="請填入要發送的內容"
        />
    
     <Button android:id="@+id/btn_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_below="@+id/et_text" android:text="發送"
        />
     
     <TextView android:id="@+id/tv_recv" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/btn_send" android:minLines="20" android:hint="接收的內容"
         />
</RelativeLayout>

3.MainActivity.java以下所示ide

package com.example.tcpdemo; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { TcpThread mt; TextView tv_recv; EditText et_text; //要發送的內容
 Button btn_send; //定義一個handler
    public Handler mHandler = new Handler() { public void handleMessage(Message msg) { //打印服務器端發來的消息
            System.out.println("read:"+msg.obj.toString()); tv_recv.append(msg.obj.toString()+"\r\n"); }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_recv = (TextView)findViewById(R.id.tv_recv); et_text = (EditText)findViewById(R.id.et_text); mt = new TcpThread(); mt.setHandler(mHandler); //設置handler
        mt.setIp("10.10.10.104");   //設置服務器地址
        mt.start();                    //啓動線程
 btn_send = (Button)findViewById(R.id.btn_send); btn_send.setOnClickListener(new OnClickListener() { //向服務器端發送數據
            public void onClick(View v) { if(!mt.write(et_text.getText().toString())) { Toast.makeText(getApplicationContext(), "發送失敗", Toast.LENGTH_SHORT).show(); } } }); } }

4.TcpThread.java以下所示post

package com.example.tcpdemo; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.net.UnknownHostException; import android.os.Handler; import android.os.Message; public class TcpThread extends Thread { Handler mHandler=null; Socket socket = null; String ip = null; OutputStream outputStream = null;        //輸出流
        InputStream inputStream=null;            //接收流 //獲取另外一個線程的Handler
        public void setHandler( Handler handler){ mHandler = handler; } //設置服務器IP
        public void setIp(String ip){ this.ip = ip; } public void run(){ try { socket = new Socket(ip, 8080);        //訪問指定的ip地址:8080

// 1 UnknownHostException:若是沒法識別主機的名字或IP地址,就會拋出這種異常。
// 2 ConnectException:若是沒有服務器進程監聽指定的端口,或者服務器進程拒絕鏈接,就會拋出這種異常。
// 3 SocketTimeoutException:若是等待鏈接超時,就會拋出這種異常。
// 4 BindException:若是沒法把Socket對象與指定的本地IP地址或端口綁定,就會拋出這種異常學習


                } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //獲取輸出流
            try { outputStream = socket.getOutputStream(); } catch (IOException e) { // TODO Auto-generated catch block
 e.printStackTrace(); } try{ while (true)         //讀取服務器端發送來的數據
 { final byte[] buffer = new byte[1024];//建立接收緩衝區
                    inputStream = socket.getInputStream(); final int len = inputStream.read(buffer);//數據讀出來,而且返回數據的長度
                    if(len>0) { Message msg = mHandler.obtainMessage(); //設置發送的內容
                         msg.obj = new String(buffer,0,len); mHandler.sendMessage(msg); } } } catch (IOException e) { } } //向服務器端寫入數據
        public boolean write(String text){ boolean ret = true; try { outputStream.write(text.toString().getBytes()); } catch (IOException e) { ret = false; e.printStackTrace(); } return ret; } }

 注意1:

使用inputStream.read(buffer)的時候若是讀取不到數據,會進入阻塞狀態,直到有數據來了,纔會退出執行下個語句.若是想不使用阻塞的話,能夠經過if(inputStream.available()>0)來判斷是否有數據來了.再讀取便可

相關文章
相關標籤/搜索