Android 網絡編程——Socket

 

Socket是對TCP/IP協議的封裝,Socket本身並不是協議,而是一個針對TCP和UDP編程的接口(API),通過Socket,我們才能使用TCP/IP協議。Socket的出現只是使得程序員更方便地使用TCP/IP協議棧而已,是對TCP/IP協議的抽象,從而形成了我們知道的一些最基本的函數接口。

一.利用Socket建立網絡連接的步驟

建立Socket連接至少需要一對套接字,其中一個運行於客戶端,稱爲ClientSocket ,另一個運行於服務器端,稱爲ServerSocket 。

套接字之間的連接過程分爲三個步驟:服務器監聽,客戶端請求,連接確認。

1。服務器監聽:服務器端套接字並不定位具體的客戶端套接字,而是處於等待連接的狀態,實時監控網絡狀態,等待客戶端的連接請求。

2。客戶端請求:指客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。爲此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然後就向服務器端套接字提出連接請求。

3。連接確認:當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發給客戶端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連接請求。

 

二.Socket 一般有兩種類型:TCP 套接字和 UDP 套接字

1.使用 TCP 通信
TCP 服務器端工作的主要步驟如下:
步驟 1 調用 ServerSocket(int port)創建一個 ServerSocket,並綁定到指定端口上。
步驟 2 調用 accept(),監聽連接請求,如果客戶端請求連接,則接受連接,返回通信套接字。
步驟 3 調 用 Socket 類 的 getOutputStream() 和 getInputStream() 獲 取 輸 出 和 輸 入 流,開始網絡數據的發送和接收。
步驟 4 關閉通信套接字。

// 創建一個 ServerSocket 對象
ServerSocket serverSocket = null;
try {
	// TCP_SERVER_PORT 爲指定的綁定端口,爲 int 類型
	serverSocket = new ServerSocket(TCP_SERVER_PORT);
	// 監聽連接請求
	Socket socket = serverSocket.accept();
	// 寫入讀 Buffer 中
	BufferedReader in = new BufferedReader(new
	// 獲取輸入流
	InputStreamReader(socket.getInputStream()));
	// 放到寫 Buffer 中
	BufferedWriter out = new BufferedWriter(new
	// 獲取輸出流
	OutputStreamWriter(socket.getOutputStream()));
	// 讀取接收信息,轉換爲字符串
	String incomingMsg = in.readLine() + System.getProperty("line.separator");
	// 生成發送字符串
	String outgoingMsg = "goodbye from port " + TCP_SERVER_PORT +
	System.getProperty("line.separator");
	// 將發送字符串寫入上面定義的 BufferedWriter 中
	out.write(outgoingMsg);
	// 刷新,發送
	out.flush();
	// 關閉
	socket.close();
} catch (InterruptedIOException e) {
	// 超時錯誤
	e.printStackTrace();
	// IO 異常
} catch (IOException e) {
	// 打印錯誤
	e.printStackTrace();
} finally {
	// 判定是否初始化 ServerSocket 對象,如果初始化則關閉 serverSocket
	if (serverSocket != null) {
		try {
			serverSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


TCP 客戶端工作的主要步驟如下:
步驟 1 調用 Socket() 創建一個流套接字,並連接到服務器端。
步驟 2 調 用 Socket 類 的 getOutputStream() 和 getInputStream() 方 法 獲 取 輸 出 和 輸 入流,開始網絡數據的發送和接收。
步驟 3 關閉通信套接字。

try {
	// 初始化 Socket,TCP_SERVER_PORT 爲指定的端口,int 類型
	Socket socket = new Socket("localhost", TCP_SERVER_PORT);
	// 獲取輸入流
	BufferedReader in = new BufferedReader(new
	InputStreamReader(socket.getInputStream()));
	// 生成輸出流
	BufferedWriter out = new BufferedWriter(new
	OutputStreamWriter(socket.getOutputStream()));
	// 生成輸出內容
	String outMsg = "TCP connecting to " + TCP_SERVER_PORT +
	System.getProperty("line.separator");
	// 寫入
	out.write(outMsg);
	// 刷新,發送
	out.flush();
	// 獲取輸入流
	String inMsg = in.readLine() + System.getProperty("line.separator");
	Log.i("TcpClient", "received: " + inMsg);
	// 關閉連接
	socket.close();
} catch (UnknownHostException e) {
	e.printStackTrace();
} catch (IOException e) {
	e.printStackTrace();
}

 

2.使用 UDP 通信
UDP 服務器端工作的主要步驟如下:
步驟 1 調用 DatagramSocket(int port) 創建一個數據報套接字,並綁定到指定端口上。
步驟 2 調用 DatagramPacket(byte[]buf,int length),建立一個字節數組以接收 UDP 包。
步驟 3 調用 DatagramSocket 類的 receive(),接受 UDP 包。
步驟 4 關閉數據報套接字。

// 接收的字節大小,客戶端發送的數據不能超過 MAX_UDP_DATAGRAM_LEN
byte[] lMsg = new byte[MAX_UDP_DATAGRAM_LEN];
// 實例化一個 DatagramPacket 類
DatagramPacket dp = new DatagramPacket(lMsg, lMsg.length);
// 新建一個 DatagramSocket 類
DatagramSocket ds = null;
try {
	// UDP 服務器監聽的端口
	ds = new DatagramSocket(UDP_SERVER_PORT);
	// 準備接收數據
	ds.receive(dp);
} catch (SocketException e) {
	e.printStackTrace();
} catch (IOException e) {
	e.printStackTrace();
} finally {
	// 如果 ds 對象不爲空,則關閉 ds 對象
	if (ds != null) {
		ds.close();
	}
}



UDP 客戶端工作的主要步驟如下:
步驟 1 調用 DatagramSocket() 創建一個數據包套接字。
步驟 2 調用 DatagramPacket(byte[]buf,int offset,int length,InetAddress address,int port),建立要發送的 UDP 包。
步驟 3 調用 DatagramSocket 類的 send() 發送 UDP 包。
步驟 4 關閉數據報套接字。

// 定義需要發送的信息
String udpMsg = "hello world from UDP client " + UDP_SERVER_PORT;
// 新建一個 DatagramSocket 對象
DatagramSocket ds = null;
try {
	// 初始化 DatagramSocket 對象
	ds = new DatagramSocket();
	// 初始化 InetAddress 對象
	InetAddress serverAddr = InetAddress.getByName("127.0.0.1");
	DatagramPacket dp;
	// 初始化 DatagramPacket 對象
	dp = new Datagram
	Packet(udpMsg.getBytes(), udpMsg.length(), serverAddr, UDP_SERVER_PORT);
	// 發送
	ds.send(dp);
	// 異常處理
	// Socket 連接異常
}catch (SocketException e) {
	e.printStackTrace();
	// 不能連接到主機
}catch (UnknownHostException e) {
	e.printStackTrace();
	// 數據流異常
} catch (IOException e) {
	e.printStackTrace();
	// 其他異常
} catch (Exception e) {
	e.printStackTrace();
} finally {
	// 如果 DatagramSocket 已經實例化,則需要將其關閉
	if (ds != null) {
	ds.close();
	}
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章