為什麼要講Socket呢?因為看過我藍芽協議(一)和藍芽協議(二)的文章的人知道,我要做的這個應用是把藍芽筆裡面的資料讀取到手機裡,就要用到基於Bluetooth協議的Socket,所以就也是為什麼在這裡我要講一下Socket編程了。 一:什麼是Socket 它實際上是網路通訊的一種介面,基於不同的協議,有各種不同的Socket,比如有基於TCP協議的Socket和基於UDP協議的Socket以及基於藍芽協議的Socket,Android中使用的是Java的Socket模型。 Socket在電腦行業通常稱為”通訊端“,用於描述IP地址和連接埠,是一個通訊鏈的控制代碼。這是一個比較抽象的概念。電腦是擁有連接埠的,每一個連接埠都可以有一個應用程式來進行通訊的使用,比如:80連接埠是HTTP協議所使用的連接埠,21連接埠是FTP協議所使用的連接埠,連接埠是電腦和外界通訊的介面,這些介面都是邏輯的介面,連接埠號碼取值的範圍是零到256乘以256減1,1024以下的連接埠都是作業系統使用的保留連接埠,以上的連接埠我們可以自由的來使用,不要和其他應用程式的連接埠衝突。 應用程式可以通過“通訊端”向網路發送請求或者應答網路的請求,這時候就把Socket分成了兩部分,一部分是伺服器端的Socket,這個Socket主要用來接收來自網路的請求,它一直監聽在某一個連接埠上。一部分是用戶端的Socket,這個Socket主要用來向網路發送資料。 二:Socket通訊模型
-UDP協議和TCP協議 UDP協議和TCP協議是互連網使用最廣的兩種協議都是基於IP的協議。第一個區別是UDP協議是一個不太靠譜的協議,UDP協議把資料都打成資料包,資料包上內建郵寄地址,也就是說我要把這個資料包發送到網路上的哪一個地址,通過網路把這個資料包發送出去,至於這個資料包是否發送到目的地,是否伺服器端接收到了這個資料包,這個協議並不保證,就像中國的郵政,你是把信寄出去了,但是郵政系統不保證對方能收到你寄送的信。TCP發送資料的時候要求接收方接收到資料之後給一個回應,也就是你是否收到了,TCP可靠一些,當我們發送一些比較重要的資料的時候一般都使用TCP協議。另外一個區別是UDP協議發送的一個資料包它的容量是有限的,而TCP協議則沒有這樣一個限制。並不是說UDP協議一定就不如TCP協議,在不同的領域有不同是使用,UDP協議好處是速度相對快些。TCP協議相對慢些。 -Socket通訊流程 應用程式通過“通訊端”也就是Socket可以選擇這兩種協議當中的一種,你可以選擇用UDP發送資料,也可以選擇用TCP發送資料,資料發送出去通過“通訊通道”也就是IP的基礎網路,來到伺服器端(接收端),就可以接收到資料了。發送資料的時候用UDP協議,接收的時候也要用UDP協議,發送資料的時候用TCP協議,接收的時候也要用TCP協議,在發送的時候指定接收端的IP地址和連接埠號碼就可以了,究竟資料包或資料是如何發送的,架構已經幫我們封裝好了,我們不去關心它了。 一:TCP協議通訊模型 1:工作流程
首先有兩部分用戶端和伺服器端,用戶端需要Socket這個類的對象,而伺服器端需要ServerSocket這個類的對象,由用戶端Socket發送一個請求,伺服器端的ServerSocket在電腦的某一個連接埠號碼上進行監聽,監聽用戶端發送的請求之後,那麼用戶端和伺服器端的一個通訊通道就建立起來了,這時候呢既可以從用戶端向伺服器端發送資料,伺服器端也可以給用戶端相應的響應。在用戶端發送資料的時候我們需要用到IO流裡面的OutputStream,通過這個OutputStream把資料發送給伺服器端,伺服器端用InputStream來讀取用戶端當中用OutputStream所寫入的資料。生活舉例:就像雙方男女朋友打電話一樣,男孩(用戶端)說話(資料)通過耳機發送到電話網路中去,當男孩說話的時候就相當於咱們這裡的通過OutputStream向互連網中寫入資料,而作為接聽的這個女孩(伺服器端)那麼男孩(用戶端)說的內容就是女孩(伺服器端)聽到的內容,那麼就是說伺服器端可以通過InputStream把用戶端當中通過OutputStream所寫入的資料給它讀取出來,反之亦然,如果伺服器端想向用戶端發送資料,那麼就使用OutputStream寫出資料,在用戶端通過InputStream把伺服器端當中通過OutputStream所寫入的資料給它讀取出來。就像打電話一樣,你說的就是我聽的,你聽的就是我說的。 二:通過基於TCP協議發送和讀取資料 1:布局檔案main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="啟動監聽線程" android:id="@+id/btn1" /> </LinearLayout>
2.1:伺服器端Socket代碼檔案MainActivity.java
package com.szy.socket; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class MainActivity extends Activity { private Button btn1 = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn1 = (Button) findViewById(R.id.btn1); //給按鈕綁定監聽器 btn1.setOnClickListener(new Btn1Listener()); } //按鈕監聽器 private class Btn1Listener implements OnClickListener { @Override public void onClick(View v) { //啟動一個線程 new ServerThread().start(); } } //線程類 private class ServerThread extends Thread { public void run() { //聲明一個ServerSocket對象 ServerSocket serverSocket = null; try { //建立一個ServerSocket對象,並讓ServerSocket在4567連接埠上監聽 serverSocket = new ServerSocket(4567); //調用 ServerSocket對象的accept()方法接收用戶端所發送的請求 //accept()這個方法是一個阻塞的方法,如果用戶端沒有發送請求,那麼代碼運行到這裡被阻塞,停在這裡不再向下運行了,一直等待accept()函數的返回,這時候突然用戶端發送一個請求,那個這個方法就會返回Socket對象, //Socket對象代表格服務器端和用戶端之間的一個串連 Socket socket = serverSocket.accept(); //從Socket對象中得到InputStream對象 //一旦通訊管道建立起來後,就是伺服器端有一個Socket,用戶端也有一個Socket,我們就可以通過伺服器端的Socket裡面的InputStream來讀取用戶端所發送的資料 InputStream inputStream = socket.getInputStream(); byte data[] = new byte[1024*4]; int i = 0; //從InputStream對象中讀取用戶端所發送的資料 while((i = inputStream.read(data)) !=1 ) Log.d("mytag",new String(data,0,i)); } catch (IOException e) { e.printStackTrace(); } finally { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
2.2:用戶端Socket代碼檔案TcpSocketClient.java
package com.szy.socketclient; import android.app.Activity; import java.net.Socket; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; public class TcpSocketClient extends Activity { public static void main(String[] args) { try { //建立一個Socket對象,指定伺服器端的IP地址和連接埠號碼 Socket socket = new Socket("192.168.1.105",4567); //使用InputStream對象讀取硬碟上的檔案 InputStream inputStream = new FileInputStream("C://www.txt"); //從Socket對象中得到OutputStream對象,準備往OutputStream對象裡寫入資料 OutputStream outputStream = socket.getOutputStream(); byte data[] = new byte[1024*4]; int i = 0; while((i = inputStream.read(data)) !=1 ) //從InputStream對象中讀取資料並寫入到 OutputStream對象當中 outputStream.write(data, 0, i); outputStream.flush(); } catch (Exception e) { e.printStackTrace(); } } }
(安卓巴士出)
歡迎熱愛安卓開發的朋友加入群學習共同進步!深圳群260134856,成都群 252743807,北京群111059554,西安群252746034,武漢群121592153,杭州群253603803