寫在開頭
依然那句話,android需要學的東西太多了。網路知識必不可少也。一點一點總結學習。
相關連結:
歡迎大家的補充,共同學習與進步。
Socket概念
Socket(套接字)用於描述IP地址和埠,是通訊鏈的控制程式碼,應用程式可以通過Socket向網路發出請求或者應答網路請求。
Socket是支援TCP/IP協議的網路通訊的基本操作單元,是對網路通訊過程中端點的抽象表示,包含了進行網路通訊所必需的5種資訊:連線所使用的協議、本地主機的IP地址、本地程式的協議埠、遠地主機的IP地址以及遠地程式的協議埠。
Socket的傳輸模式
Socket有兩種主要的操作方式:面向連線(TCP)的和無連線(UDP)的。(對於這方面,可看下上面推薦的文章)。
TCP層則提供面向應用的可靠(tcp)的或非可靠(UDP)的資料傳輸機制,這是網路程式設計的主要物件,一般不需要關心IP層是如何處理資料的。
目前較為流行的網路程式設計模型是客戶機/伺服器(C/S)結構。即通訊雙方一方作為伺服器等待客戶提出請求並予以響應。客戶則在需要服務時向伺服器提 出申請。伺服器一般作為守護程式始終執行,監聽網路埠,一旦有客戶請求,就會啟動一個服務程式來響應該客戶,同時自己繼續監聽服務埠,使後來的客戶也能及時得到服務。
TCP是Tranfer Control Protocol的 簡稱,是一種面向連線的保證可靠傳輸的協議。通過TCP協議傳輸,得到的是一個順序的無差錯的資料流。傳送方和接收方的成對的兩個socket之間必須建 立連線,以便在TCP協議的基礎上進行通訊,當一個socket(通常都是server socket)等待建立連線時,另一個socket可以要求進行連線,一旦這兩個socket連線起來,它們就可以進行雙向資料傳輸,雙方都可以進行傳送或接收操作。TCP在網路通訊上有極強的生命力,例如遠端連線(Telnet)和檔案傳輸(FTP)都需要不定長度的資料被可靠地傳輸。但是可靠的傳輸是要付出代價的,對資料內容正確性的檢驗必然佔用計算機的處理時間和網路的頻寬,因此TCP傳輸的效率不如UDP高。
UDP是User Datagram Protocol的簡稱,是一種無連線的協議,每個資料包都是一個獨立的資訊,包括完整的源地址或目的地址,它在網路上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。UDP操作簡單,而且僅需要較少的監護,因此通常用於區域網高可靠性的分散系統中client/server應用程式。例如視訊會議系統,並不要求音訊視訊資料絕對的正確,只要保證連貫性就可以了,這種情況下顯然使用UDP會更合理一些。
知識點對比: UDP: 1,每個資料包中都給出了完整的地址資訊,因此無需要建立傳送方和接收方的連線。 2,UDP傳輸資料時是有大小限制的,每個被傳輸的資料包必須限定在64KB之內。 3,UDP是一個不可靠的協議,傳送方所傳送的資料包並不一定以相同的次序到達接收方
TCP: 1,面向連線的協議,在socket之間進行資料傳輸之前必然要建立連線,所以在TCP中需要連線時間。 2,TCP傳輸資料大小限制,一旦連線建立起來,雙方的socket就可以按統一的格式傳輸大的資料。 3,TCP是一個可靠的協議,它確保接收方完全正確地獲取傳送方所傳送的全部資料。
Socket的使用(以TCP為例)(先說句,網路許可權要開啟)
客戶端和伺服器端的輸入輸出流的問題(圖解,網上一張圖,挺好。)
Socket提供了方法getInputStream()和getOutPutStream()來獲得對應的輸入流和輸出流,以便對Socket進行讀寫操作,這兩個方法的返回值分別是InputStream和OutPutStream物件。
步驟詳解
伺服器端的步驟:
1,指定埠例項化一個ServerSocket 2,呼叫ServerSocket的accept方法等待連線期間阻塞 3,獲取位於底層的Socket流進行讀寫操作 4,將資料封裝成流 5,對Socket進行讀寫 6,關閉流
客戶端的步驟:
1,通過IP地址和埠例項化Socket,請求連線伺服器 2,獲取位於底層的Socket流進行讀寫操作 3,將資料封裝成流(BufferedReader/PrintWriter,DataOutputStream/DataInputStream)的例項 4,對Socket進行讀寫 5,關閉流
Socket的構造方法
Java在包java.net中提供了兩個類Socket和ServerSocket,分別用來表示雙向連線的Socket客戶端和伺服器端。
Socket的構造方法如下:
(1)Socket(InetAddress address, int port); (2)Socket(InetAddress address, int port, boolean stream); (3)Socket(String host, int port); (4)Socket(String host, int port, boolean stream); (5)Socket(SocketImpl impl); (6)Socket(String host, int port, InetAddress localAddr, int localPort); (7)Socket(InetAddress address, int port, InetAddrss localAddr, int localPort);
ServerSocket的構造方法如下:
(1)ServerSocket(int port); (2)ServerSocket(int port, int backlog); (3)ServerSocket(int port, int backlog, InetAddress bindAddr);
其中,引數address、host和port分別是雙向連線中另一方的IP地址、主機名和埠號;引數stream表示Socket是流Socket還是資料包Socket;引數localAddr和localPort表示本地主機的IP地址和埠號;SocketImpl是Socket的父類,既可以用來建立ServerSocket,也可以用來建立Socket。
注意,在選擇埠時,必須小心。每一個埠提供一種特定的服務,只有給出正確的埠,才 能獲得相應的服務。0~1023的埠號為系統所保留,例如http服務的埠號為80,telnet服務的埠號為21,ftp服務的埠號為23, 所以我們在選擇埠號時,最好選擇一個大於1023的數以防止發生衝突。 在建立socket時如果發生錯誤,將產生IOException,在程式中必須對之作出處理。所以在建立Socket或ServerSocket是必須捕獲或丟擲例外。
簡單程式碼實現
伺服器端:(建議用MyEclipse寫個簡單的java檔案)
public class ServerSocketDemo{
public static void main(String[] args) {
new ServerThread().start();
}
}
// 建立一個執行緒在後臺監聽(例子就是用一個死迴圈,實際否。)
class ServerThread extends Thread {
private static int Port = 52000;
ServerSocket serversocket = null;
public void run() {
try {
// 建立一個serversocket物件,並讓他在Port埠監聽
serversocket = new ServerSocket(Port);
while (true) {
// 呼叫serversocket的accept()方法,接收客戶端傳送的請求
Socket socket = serversocket.accept();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// 讀取資料
String msg = buffer.readLine();
System.out.println("msg:" + msg);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
serversocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
複製程式碼
android的客戶端:
public class Client extends Activity {
private static String IpAddress = "192.168.1.12";
private static int Port = 52000;
private EditText edittext = null;
private Button send = null;
Socket socket = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
edittext = (EditText) findViewById(R.id.edittext);
send = (Button) findViewById(R.id.send);
send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
sendMsg();
}
});
}
// 傳送資訊
public void sendMsg() {
try {
// 建立socket物件,指定伺服器端地址和埠號
socket = new Socket(IpAddress, Port);
// 獲取 Client 端的輸出流
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
// 填充資訊
out.println(edittext.getText());
System.out.println("msg=" + edittext.getText());
// 關閉
out.close();
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
複製程式碼
總結
寫這麼多隻是想擴充下socket程式設計的認知,實際開發中我們一般是不會自己寫socket的,對於我們android端的即時通訊功能,一般會採用三方的解決方案,環信,融雲都是很好的選擇,如果需求必須用到socket的話,有很多框架也可以選擇。
https://github.com/vilyever/AndroidSocketClient (國庫,註釋都是中文哦)
github.com/typ0520/biz…(支援RxJava,沒用,你可以試一下給點反饋嘿嘿)
寫在最後
試了下,確實是能收到訊息的,不過我只是簡單的學習了下。在這裡感謝以下大神的部落格。
http://blog.csdn.net/liuyi1207164339/article/details/50960477
http://blog.csdn.net/x605940745/article/details/17001641
https://www.cnblogs.com/menlsh/archive/2013/06/12/3133296.html