1. 程式人生 > >基於android的Socket通訊

基於android的Socket通訊

有關通訊原理內容是在網上或百科整理得到,程式碼部分為本人所寫,如果不當,還望指教。

一、Socket通訊簡介 

Android與伺服器的通訊方式主要有兩種,一是Http通訊,一是Socket通訊。兩者的最大差異在於,http連線使用的是“請求—響應方式”,即在請求時建立連線通道,當客戶端向伺服器傳送請求後,伺服器端才能向客戶端返回資料。而Socket通訊則是在雙方建立起連線後就可以直接進行資料的傳輸,在連線時可實現資訊的主動推送,而不需要每次由客戶端想伺服器傳送請求。 那麼,什麼是socket?Socket又稱套接字,在程式內部提供了與外界通訊的埠,即埠通訊。通過建立socket連線,可為通訊雙方的資料傳輸傳提供通道。socket的主要特點有資料丟失率低,使用簡單且易於移植。


1.1什麼是Socket Socket
是一種抽象層,應用程式通過它來發送和接收資料,使用Socket可以將應用程式新增到網路中,與處於同一網路中的其他應用程式進行通訊。簡單來說,Socket提供了程式內部與外界通訊的埠併為通訊雙方的提供了資料傳輸通道。


 1.2Socket的分類
 根據不同的的底層協議,Socket的實現是多樣化的。本指南中只介紹TCP/IP協議族的內容,在這個協議族當中主要的Socket型別為流套接字(streamsocket)和資料報套接字(datagramsocket)。流套接字將TCP作為其端對端協議,提供了一個可信賴的位元組流服務。資料報套接字使用UDP協議,提供資料打包傳送服務。 下面,我們來認識一下這兩種Socket型別的基本實現模型。

二、Socket 基本通訊模型


三、Socket基本實現原理

 3.1基於TCP協議的Socket 
伺服器端首先宣告一個ServerSocket物件並且指定埠號,然後呼叫Serversocket的accept()方法接收客戶端的資料。accept()方法在沒有資料進行接收的處於堵塞狀態。(Socketsocket=serversocket.accept()),一旦接收到資料,通過inputstream讀取接收的資料。
 客戶端建立一個Socket物件,指定伺服器端的ip地址和埠號(Socketsocket=newSocket("172.168.10.108",8080);),通過inputstream讀取資料,獲取伺服器發出的資料(OutputStreamoutputstream=socket.getOutputStream()),最後將要傳送的資料寫入到outputstream即可進行TCP協議的socket資料傳輸。
3.2基於UDP協議的資料傳輸 


伺服器端首先建立一個DatagramSocket物件,並且指點監聽的埠。接下來建立一個空的DatagramSocket物件用於接收資料(bytedata[]=newbyte[1024;]DatagramSocketpacket=newDatagramSocket(data,data.length)),使用DatagramSocket的receive方法接收客戶端傳送的資料,receive()與serversocket的accepet()類似,在沒有資料進行接收的處於堵塞狀態。
客戶端也建立個DatagramSocket物件,並且指點監聽的埠。接下來建立一個InetAddress物件,這個物件類似與一個網路的傳送地址(InetAddressserveraddress=InetAddress.getByName("172.168.1.120")).定義要傳送的一個字串,建立一個DatagramPacket物件,並制定要講這個資料報包傳送到網路的那個地址以及埠號,最後使用DatagramSocket的物件的send()傳送資料。*(Stringstr="hello";bytedata[]=str.getByte();DatagramPacketpacket=new DatagramPacket(data,data.length,serveraddress,4567);socket.send(packet);)

四、android 實現socket簡單通訊

前言:新增許可權

  1. <!--允許應用程式改變網路狀態-->    
  2. <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>    
  3. <!--允許應用程式改變WIFI連線狀態-->    
  4. <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>    
  5. <!--允許應用程式訪問有關的網路資訊-->    
  6. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>    
  7. <!--允許應用程式訪問WIFI網絡卡的網路資訊-->    
  8. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>    
  9. <!--允許應用程式完全使用網路-->    
  10. <uses-permission android:name="android.permission.INTERNET"/>    

4.1使用TCP協議通訊

android端實現:

  1. protectedvoid connectServerWithTCPSocket() {  
  2.         Socket socket;  
  3.         try {// 建立一個Socket物件,並指定服務端的IP及埠號
  4.             socket = new Socket("192.168.1.32"1989);  
  5.             // 建立一個InputStream使用者讀取要傳送的檔案。
  6.             InputStream inputStream = new FileInputStream("e://a.txt");  
  7.             // 獲取Socket的OutputStream物件用於傳送資料。
  8.             OutputStream outputStream = socket.getOutputStream();  
  9.             // 建立一個byte型別的buffer位元組陣列,用於存放讀取的本地檔案
  10.             byte buffer[] = newbyte[4 * 1024];  
  11.             int temp = 0;  
  12.             // 迴圈讀取檔案
  13.             while ((temp = inputStream.read(buffer)) != -1) {  
  14.                 // 把資料寫入到OuputStream物件中
  15.                 outputStream.write(buffer, 0, temp);  
  16.             }  
  17.             // 傳送讀取的資料到服務端
  18.             outputStream.flush();  
  19.             /** 或建立一個報文,使用BufferedWriter寫入,看你的需求 **/
  20. //          String socketData = "[2143213;21343fjks;213]";
  21. //          BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
  22. //                  socket.getOutputStream()));
  23. //          writer.write(socketData.replace("\n", " ") + "\n");
  24. //          writer.flush();
  25.             /************************************************/
  26.         } catch (UnknownHostException e) {  
  27.             e.printStackTrace();  
  28.         } catch (IOException e) {  
  29.             e.printStackTrace();  
  30.         }  
  31.     }  

伺服器端簡單實現:
  1. publicvoid ServerReceviedByTcp() {  
  2.     // 宣告一個ServerSocket物件
  3.     ServerSocket serverSocket = null;  
  4.     try {  
  5.         // 建立一個ServerSocket物件,並讓這個Socket在1989埠監聽
  6.         serverSocket = new ServerSocket(1989);  
  7.         // 呼叫ServerSocket的accept()方法,接受客戶端所傳送的請求,
  8.         // 如果客戶端沒有傳送資料,那麼該執行緒就停滯不繼續
  9.         Socket socket = serverSocket.accept();  
  10.         // 從Socket當中得到InputStream物件
  11.         InputStream inputStream = socket.getInputStream();  
  12.         byte buffer[] = newbyte[1024 * 4];  
  13.         int temp = 0;  
  14.         // 從InputStream當中讀取客戶端所傳送的資料
  15.         while ((temp = inputStream.read(buffer)) != -1) {  
  16.             System.out.println(new String(buffer, 0, temp));  
  17.         }  
  18.         serverSocket.close();  
  19.     } catch (IOException e) {  
  20.         e.printStackTrace();  
  21.     }  
  22. }  

4.2使用UDP協議通訊

客戶端傳送資料實現:

  1. protectedvoid connectServerWithUDPSocket() {  
  2.     DatagramSocket socket;  
  3.     try {  
  4.         //建立DatagramSocket物件並指定一個埠號,注意,如果客戶端需要接收伺服器的返回資料,
  5.         //還需要使用這個埠號來receive,所以一定要記住
  6.         socket = new DatagramSocket(1985);  
  7.         //使用InetAddress(Inet4Address).getByName把IP地址轉換為網路地址  
  8.         InetAddress serverAddress = InetAddress.getByName("192.168.1.32");  
  9.         //Inet4Address serverAddress = (Inet4Address) Inet4Address.getByName("192.168.1.32");  
  10.         String str = "[2143213;21343fjks;213]";//設定要傳送的報文  
  11.         byte data[] = str.getBytes();//把字串str字串轉換為位元組陣列  
  12.         //建立一個DatagramPacket物件,用於傳送資料。  
  13.         //引數一:要傳送的資料  引數二:資料的長度  引數三:服務端的網路地址  引數四:伺服器端埠號 
  14.         DatagramPacket packet = new DatagramPacket(data, data.length ,serverAddress ,10025);    
  15.         socket.send(packet);//把資料傳送到服務端。  
  16.     } catch (SocketException e) {  
  17.         e.printStackTrace();  
  18.     } catch (UnknownHostException e) {  
  19.         e.printStackTrace();  
  20.     } catch (IOException e) {  
  21.         e.printStackTrace();  
  22.     }    
  23. }  

客戶端接收伺服器返回的資料:
  1. publicvoid ReceiveServerSocketData() {  
  2.     DatagramSocket socket;  
  3.     try {  
  4.         //例項化的埠號要和傳送時的socket一致,否則收不到data
  5.         socket = new DatagramSocket(1985);  
  6.         byte data[] = newbyte[4 * 1024];  
  7.         //引數一:要接受的data 引數二:data的長度
  8.         DatagramPacket packet = new DatagramPacket(data, data.length);  
  9.         socket.receive(packet);  
  10.         //把接收到的data轉換為String字串
  11.         String result = new String(packet.getData(), packet.getOffset(),  
  12.                 packet.getLength());  
  13.         socket.close();//不使用了記得要關閉
  14.         System.out.println("the number of reveived Socket is  :" + flag  
  15.                 + "udpData:" + result);  
  16.     } catch (SocketException e) {  
  17.         e.printStackTrace();  
  18.     } catch (IOException e) {  
  19.         e.printStackTrace();  
  20.     }  
  21. }  

伺服器接收客戶端實現:
  1. publicvoid ServerReceviedByUdp(){  
  2.     //建立一個DatagramSocket物件,並指定監聽埠。(UDP使用DatagramSocket)  
  3.     DatagramSocket socket;  
  4.     try {  
  5.         socket = new DatagramSocket(10025);  
  6.         //建立一個byte型別的陣列,用於存放接收到得資料  
  7.         byte data[] = newbyte[4*1024];    
  8.         //建立一個DatagramPacket物件,並指定DatagramPacket物件的大小  
  9.         DatagramPacket packet = new DatagramPacket(data,data.length);    
  10.         //讀取接收到得資料  
  11.         socket.receive(packet);    
  12.         //把客戶端傳送的資料轉換為字串。  
  13.         //使用三個引數的String方法。引數一:資料包 引數二:起始位置 引數三:資料包長  
  14.         String result = new String(packet.getData(),packet.getOffset() ,packet.getLength());    
  15.     } catch (SocketException e) {  
  16.         e.printStackTrace();  
  17.     } catch (IOException e) {  
  18.         e.printStackTrace();  
  19.     }    
  20. }  


五、總結:

使用UDP方式android