Socket 通訊原理(Android用戶端和伺服器以TCP&&UDP方式互連)

來源:互聯網
上載者:User

標籤:調用   串連   通道   socket   簡單實現   txt   streams   接下來   串連狀態   

ZERO、前言

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

一、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簡單通訊

前言:添加許可權

<!--允許應用程式改變網路狀態-->  <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端實現:

    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();        }    }

伺服器端簡單實現:

    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協議通訊

用戶端發送資料實現:

    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();        }      }

用戶端接收伺服器返回的資料:

    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();        }    }

伺服器接收用戶端實現:

    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();        }      }

五、總結:

使用UDP方式android端和伺服器端接收可以看出,其實android端和伺服器端的發送和接收大庭相徑,只要連接埠號碼正確了,相互連信就沒有問題,TCP使用的是流的方式發送,UDP是以包的形式發送。

demo地址:http://download.csdn.NET/detail/mad1989/5626975

Socket 通訊原理(Android用戶端和伺服器以TCP&&UDP方式互連)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.