Socket網絡通信

Socket通信

參考:
  1. 國內博客
  2. 維基百科
  3. IBM Knowledge
  4. 國外技術分享的文章
  5. Oracle官方文檔

簡介

Android與服務器的通信方式主要有兩種,一是Http通信,一是Socket通信。兩者的最大差異在于,http連接使用的是“請求—響應方式”,即在請求時建立連接通道,當客戶端向服務器發送請求后,服務器端才能向客戶端返回數據。而Socket通信則是在雙方建立起連接后就可以直接進行數據的傳輸,在連接時可實現信息的主動推送,而不需要每次由客戶端想服務器發送請求。

功能上最大的差異:Http通信是客戶端主動發送,服務端被動接收;Socket通信是雙方互發。

分類

Socket類型為:

  • 流套接字、面向連接的套接字(streamsocket,connection_oriented sockets):使用TCP、SCTP或者DCCP傳輸協議。
  • 數據報套接字、無連接的套接字(datagramsocket,connectionless sockets):使用UDP協議。
  • 原始套接字(raw 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數據傳輸。

  • 數據包套接字

服務器端首先創建一個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);)

TCP與UPD實現的最大的區別:TCP使用的是流的方式發送,UPD是以包的形勢發送。

通信模型

網絡傳輸中,Socket的APIs 處于應用層和傳輸層之間。Socket APIs本身不組成通信模型。它允許應用與傳輸層或者其他傳統的通信模型進行交互。具體如下所示:


Java編碼

偽代碼:

Socket socket = getSocket(type = "TCP")
connect(socket, address = "1.2.3.4", port = "80")
send(socket, "Hello, world!")
close(socket)

Java服務端代碼:
創建Socket并監聽:

public void listenSocket(){
    try{
        server = new ServerSocket(4321); 
    } catch (IOException e) {
        System.out.println("Could not listen on port 4321");
        System.exit(-1);
    }

listenSocketSocketserver.acceptSocket
    try{
        client = server.accept();
    } catch (IOException e) {
        System.out.println("Accept failed: 4321");
        System.exit(-1);
    }

listenSocketBufferedReaderclientPrintWriter
  try{
        in = new BufferedReader(new InputStreamReader(client.getInputStream()));
        out = new PrintWriter(client.getOutputStream(), true);
    } catch (IOException e) {
        System.out.println("Read failed");
        System.exit(-1);
    }
}

listenSocket
while(true){
  try{
    line = in.readLine();
//Send data back to client
    out.println(line);
  } catch (IOException e) {
    System.out.println("Read failed");
    System.exit(-1);
  }
}

客戶端發代碼:

public void listenSocket(){
//Create socket connection
try{
     socket = new Socket("kq6py", 4321);
 out = new PrintWriter(socket.getOutputStream(), 
             true);
 in = new BufferedReader(new InputStreamReader(
            socket.getInputStream()));
   } catch (UnknownHostException e) {
 System.out.println("Unknown host: kq6py");
 System.exit(1);
   } catch  (IOException e) {
 System.out.println("No I/O");
 System.exit(1);
   }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容