1、Socket通訊簡介 java
Android與服務器的通訊方式主要有兩種,一是Http通訊,一是Socket通訊。二者的最大差別在於,http鏈接使用的是「請求—響應方式」,即在請求時創建鏈接通道,當客戶端向服務器發送請求後,服務器端才能向客戶端返回數據。而Socket通訊則是在雙方創建起鏈接後就能夠直接進行數據的傳輸,在鏈接時可實現信息的主動推送,而不須要每次由客戶端想服務器發送請求。 那麼,什麼是socket?Socket又稱套接字,在程序內部提供了與外界通訊的端口,即端口通訊。經過創建socket鏈接,可爲通訊雙方的數據傳輸傳提供通道。socket的主要特色有數據丟失率低,使用簡單且易於移植。android
1.1什麼是Socket Socket
是一種抽象層,應用程序經過它來發送和接收數據,使用Socket能夠將應用程序添加到網絡中,與處於同一網絡中的其餘應用程序進行通訊。簡單來講,Socket提供了程序內部與外界通訊的端口併爲通訊雙方的提供了數據傳輸通道。數組
1.2Socket的分類
根據不一樣的的底層協議,Socket的實現是多樣化的。本指南中只介紹TCP/IP協議族的內容,在這個協議族當中主要的Socket類型爲流套接字(streamsocket)和數據報套接字(datagramsocket)。流套接字將TCP做爲其端對端協議,提供了一個可信賴的字節流服務。數據報套接字使用UDP協議,提供數據打包發送服務。 下面,咱們來認識一下這兩種Socket類型的基本實現模型。服務器
2、Socket 基本通訊模型網絡
![](http://static.javashuo.com/static/loading.gif)
3、Socket基本實現原理app
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);)socket
4、android 實現socket簡單通訊spa
前言:添加權限.net
[java] view plaincopy線程
- <!--容許應用程序改變網絡狀態-->
- <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
-
- <!--容許應用程序改變WIFI鏈接狀態-->
- <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
-
- <!--容許應用程序訪問有關的網絡信息-->
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
-
- <!--容許應用程序訪問WIFI網卡的網絡信息-->
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
-
- <!--容許應用程序徹底使用網絡-->
- <uses-permission android:name="android.permission.INTERNET"/>
4.1使用TCP協議通訊
android端實現:
[java] view plaincopy
- protected void connectServerWithTCPSocket() {
-
- Socket socket;
- try {// 建立一個Socket對象,並指定服務端的IP及端口號
- socket = new Socket("192.168.1.32", 1989);
- // 建立一個InputStream用戶讀取要發送的文件。
- InputStream inputStream = new FileInputStream("e://a.txt");
- // 獲取Socket的OutputStream對象用於發送數據。
- OutputStream outputStream = socket.getOutputStream();
- // 建立一個byte類型的buffer字節數組,用於存放讀取的本地文件
- byte buffer[] = new byte[4 * 1024];
- int temp = 0;
- // 循環讀取文件
- while ((temp = inputStream.read(buffer)) != -1) {
- // 把數據寫入到OuputStream對象中
- outputStream.write(buffer, 0, temp);
- }
- // 發送讀取的數據到服務端
- outputStream.flush();
-
- /** 或建立一個報文,使用BufferedWriter寫入,看你的需求 **/
- // String socketData = "[2143213;21343fjks;213]";
- // BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- // socket.getOutputStream()));
- // writer.write(socketData.replace("\n", " ") + "\n");
- // writer.flush();
- /************************************************/
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
服務器端簡單實現:
[java] view plaincopy
- public void ServerReceviedByTcp() {
- // 聲明一個ServerSocket對象
- ServerSocket serverSocket = null;
- try {
- // 建立一個ServerSocket對象,並讓這個Socket在1989端口監聽
- serverSocket = new ServerSocket(1989);
- // 調用ServerSocket的accept()方法,接受客戶端所發送的請求,
- // 若是客戶端沒有發送數據,那麼該線程就停滯不繼續
- Socket socket = serverSocket.accept();
- // 從Socket當中獲得InputStream對象
- InputStream inputStream = socket.getInputStream();
- byte buffer[] = new byte[1024 * 4];
- int temp = 0;
- // 從InputStream當中讀取客戶端所發送的數據
- while ((temp = inputStream.read(buffer)) != -1) {
- System.out.println(new String(buffer, 0, temp));
- }
- serverSocket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
4.2使用UDP協議通訊
客戶端發送數據實現:
[java] view plaincopy
- protected void connectServerWithUDPSocket() {
-
- DatagramSocket socket;
- try {
- //建立DatagramSocket對象並指定一個端口號,注意,若是客戶端須要接收服務器的返回數據,
- //還須要使用這個端口號來receive,因此必定要記住
- socket = new DatagramSocket(1985);
- //使用InetAddress(Inet4Address).getByName把IP地址轉換爲網絡地址
- InetAddress serverAddress = InetAddress.getByName("192.168.1.32");
- //Inet4Address serverAddress = (Inet4Address) Inet4Address.getByName("192.168.1.32");
- String str = "[2143213;21343fjks;213]";//設置要發送的報文
- byte data[] = str.getBytes();//把字符串str字符串轉換爲字節數組
- //建立一個DatagramPacket對象,用於發送數據。
- //參數一:要發送的數據 參數二:數據的長度 參數三:服務端的網絡地址 參數四:服務器端端口號
- DatagramPacket packet = new DatagramPacket(data, data.length ,serverAddress ,10025);
- socket.send(packet);//把數據發送到服務端。
- } catch (SocketException e) {
- e.printStackTrace();
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
客戶端接收服務器返回的數據:
[java] view plaincopy
- public void ReceiveServerSocketData() {
- DatagramSocket socket;
- try {
- //實例化的端口號要和發送時的socket一致,不然收不到data
- socket = new DatagramSocket(1985);
- byte data[] = new byte[4 * 1024];
- //參數一:要接受的data 參數二:data的長度
- DatagramPacket packet = new DatagramPacket(data, data.length);
- socket.receive(packet);
- //把接收到的data轉換爲String字符串
- String result = new String(packet.getData(), packet.getOffset(),
- packet.getLength());
- socket.close();//不使用了記得要關閉
- System.out.println("the number of reveived Socket is :" + flag
- + "udpData:" + result);
- } catch (SocketException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
服務器接收客戶端實現:
[java] view plaincopy
- public void ServerReceviedByUdp(){
- //建立一個DatagramSocket對象,並指定監聽端口。(UDP使用DatagramSocket)
- DatagramSocket socket;
- try {
- socket = new DatagramSocket(10025);
- //建立一個byte類型的數組,用於存放接收到得數據
- byte data[] = new byte[4*1024];
- //建立一個DatagramPacket對象,並指定DatagramPacket對象的大小
- DatagramPacket packet = new DatagramPacket(data,data.length);
- //讀取接收到得數據
- socket.receive(packet);
- //把客戶端發送的數據轉換爲字符串。
- //使用三個參數的String方法。參數一:數據包 參數二:起始位置 參數三:數據包長
- String result = new String(packet.getData(),packet.getOffset() ,packet.getLength());
- } catch (SocketException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
5、總結:
使用UDP方式android端和服務器端接收能夠看出,其實android端和服務器端的發送和接收大庭相徑,只要端口號正確了,相互通訊就沒有問題,TCP使用的是流的方式發送,UDP是以包的形式發送。
demo地址:http://download.csdn.net/detail/mad1989/5626975