天天看點

Java4Android之socket網絡通信基礎

本節主要介紹socket程式設計,發現java裡面的socket程式設計和c語言的還是有一些不一樣,比如tcp socket ,在java中區分了serversocket。不過原理都一樣,在流程處理上也非常相似,是以,了解起來并不難。我們會先從基礎說起,從如何建立socket連接配接,到如何實作一個合理的設計例如在android中,我們發送一條消息,然後監聽一個回複,如何做到不卡死ui,本文将會由淺入深的為大家呈現一個相對完整的android socket程式設計。

在進入java 的socket程式設計之前,我們從原理上切入,然後提及相應的代碼說明。

socket可以說是一種針對網絡的抽象,應用通過它可以來針對網絡讀寫資料。就像通過一個檔案的file handler就可以都寫資料到儲存設備上一樣。根據tcp協定和udp協定的不同,在網絡程式設計方面就有面向兩個協定的不同socket,一個是面向位元組流的一個是面向封包的。

Java4Android之socket網絡通信基礎

  tcp主要是面向連接配接的協定,它包含有建立和拆除連接配接,保證資料流的順序和正确性等功能。每次對tcp中間的資料操作相當于對一個資料流進行通路。它最典型的特征就是那三次握手的建立連接配接過程。tcp的連接配接建立和撤銷過程如下圖:

Java4Android之socket網絡通信基礎

server端所要做的事情主要是建立一個通信的端點,然後等待用戶端發送的請求。典型的處理步驟如下:

1. 建構一個serversocket執行個體,指定本地的端口。這個socket就是用來監聽指定端口的連接配接請求的。

2.重複如下幾個步驟:

a. 調用socket的accept()方法來獲得下面用戶端的連接配接請求。通過accept()方法傳回的socket執行個體,建立了一個和用戶端的新連接配接。

b.通過這個傳回的socket執行個體擷取inputstream和outputstream,可以通過這兩個stream來分别讀和寫資料。

c.結束的時候調用socket執行個體的close()方法關閉socket連接配接。

這個流程的典型示例代碼如下:

上述是單線程版本的伺服器流程,也可是是多線程的。大體代碼如下:

用戶端的請求過程稍微有點不一樣:

1.建構socket執行個體,通過指定的遠端伺服器位址和端口來建立連接配接。

2.通過socket執行個體包含的inputstream和outputstream來進行資料的讀寫。

3.操作結束後調用socket執行個體的close方法,關閉。

示例代碼如下;

上述代碼就是一個完整的用戶端/伺服器結構的socket通信代碼。

但是,在android中的socket通信中,我們可以想象一下這樣的場景。我在edittext裡面輸入了一句“你好”,然後我按發送button按鈕,就把消息發送給了遠端的伺服器,然後伺服器給我回了一個“你好,歡迎您!”。我們發送完第一條資訊的時候,我們要阻塞在那裡等伺服器的話,會發生什麼?我們 ui是不是會卡死?是以,很明顯,這樣的設計是不合理的。

myclientactivity.java檔案,主要是定義了一個繼承自thread類的用于接收資料的類,覆寫了其中的run()方法,在這個函數裡面接收資料,接收到資料後就通過handler發送消息,收到消息後在ui線程裡更新接收到的資料。完整的内容如下:

myserveractivity.java檔案,定義了兩個thread子類,一個用于監聽用戶端的連接配接,一個用于接收資料,其他地方與myclientactivity.java差不多。完整的内容如下:

上述代碼就是實作了真實環境下android的socket通信。

udp和tcp有兩個典型的差別,一個就是它不需要建立連接配接,另外就是它在每次收發的封包都保留了消息的邊界。

因為udp協定不需要建立連接配接,它的過程如下:

1. 構造datagramsocket執行個體,指定本地端口。

2. 通過datagramsocket執行個體的receive方法接收datagrampacket.datagrampacket中間就包含了通信的内容。

3. 通過datagramsocket的send和receive方法來收和發datagrampacket.

典型的互動流程代碼如下:

udp用戶端的步驟也比較簡單,主要包括下面3步:

1. 構造datagramsocket執行個體。

2.通過datagramsocket執行個體的send和receive方法發送datagrampacket封包。

3.結束後,調用datagramsocket的close方法關閉。

因為和tcp不同,udp發送封包的時候可以在同一個本地端口随意發送給不同的伺服器,一般不需要在udp的datagramsocket的構造函數中指定目的伺服器的位址。

另外,udp用戶端還有一個重要的不同就是,tcp用戶端發送echo連接配接消息之後會在調用read方法的時候進入阻塞狀态,而udp這樣卻不行。因為udp中間是可以允許封包丢失的。如果封包丢失了,程序一直在阻塞或者挂起的狀态,則程序會永遠沒法往下走了。是以會一般設定一個setsotimeout方法,指定在多久的時間内沒有收到封包就放棄。也可以通過指定一個數字,循環指定的次數來讀取封包,讀到就傳回,否則就放棄。

一個典型的udp client代碼示例如下:

這次的socket程式設計就說道這裡,裡面參考和引用轉載了不少别人的東西,mark一下。

reference:

http://shmilyaw-hotmail-com.iteye.com/blog/1556187

http://www.cnblogs.com/lknlfy/archive/2012/03/04/2379628.html