您好,登錄后才能下訂單哦!
簡述
Java中Socket分為普通Socket和NioSocket兩種,這里介紹Socket。
我們可以把Socket比作兩個城市間的交通工具,有了它可以在兩城之間來回穿梭,交通工具有很多種,每種交通工具也有相應的交通規則。Socket也一樣,也有多種。大多情況下使用的是TCP/IP的流套接字,它是一種穩定的通信協議。(TCP/IP與UDP的對比)
Java中的網絡通信是通過Socket實現的,Socket分為ServerSocket和Socket兩大類,ServerSocket用于服務端,通過accept方法監聽請求,監聽到請求后返回Socket,Socket用于具體完成數據傳輸,客戶端直接使用Socket發起請求并傳輸數據。
ServerSocket的使用可以分為三步:
1.創建ServerSocket。ServerSocket的構造方法一共有5個,通常用的是ServerSocket(int port),只需要端口號(port)即可。
2.調用創建出來的ServerSocket的accept方法進行監聽。accept方法時阻塞方法,也就是說調用accept方法后程序會停下來等待連接請求,在接收到請求之前程序將不會往下走。當接收到請求后accept方法會返回一個Socket。
3.使用accept方法返回的Socket與客戶端進行通信。
栗子
Client:
package IO; import java.io.*; import java.net.Socket; import java.util.Date; /** * Created by zhengbin06 on 2017/2/2. */ public class Client { public static void main(String[] args) { String msg = "Client Data"; try { Socket socket = new Socket("127.0.0.1", 9090); // 先寫、再讀 PrintWriter printWriter = new PrintWriter(socket.getOutputStream()); // 發送數據 printWriter.println(msg); printWriter.flush(); // 獲得服務端返回的數據 BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line = bufferedReader.readLine(); System.out.println("received from server: " + line + "\ttime=" + new Date().getTime()); // 關閉資源 printWriter.close(); bufferedReader.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
Server:
package IO; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Date; /** * Created by zhengbin06 on 2017/2/2. */ public class Server { private static Socket socket = null; private static ServerSocket serverSocket = null; public static void main(String[] args) throws IOException { BufferedReader bufferedReader = null; PrintWriter printWriter = null; try { // 創建一個ServerSocket監聽9090端口 serverSocket = new ServerSocket(9090); while (true) { System.out.println("開始等待請求。。。。"); // 等待請求 // 監聽并接受到此套接字的連接。此方法在連接傳入之前一直阻塞。 socket = serverSocket.accept(); System.out.println("接收到請求:" + socket.toString() + "\ttime=" + new Date().getTime()); // 接收到請求后使用socket進行通信, 創建BufferedReader用于讀取數據 bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line = bufferedReader.readLine(); System.out.println("received from client: " + line + "\ttime=" + new Date().getTime()); // 創建PrintWriter, 用于發送數據 printWriter = new PrintWriter(socket.getOutputStream()); printWriter.println("received data: " + line + "\ttime=" + new Date().getTime()); printWriter.flush(); } } finally { // 關閉所有資源 bufferedReader.close(); printWriter.close(); socket.close(); serverSocket.close(); } } }
細節
監聽請求:
當一個新的Socket請求來到時,將為這個連接創建一個新的套接字數據結構,該套接字數據的信息包含的地址和端口正式請求源地址和端口。這個新創建的數據結構將會關聯到ServerSocket實例的一個未完成的連接數據結構列表中。注意,這時服務端的與之對應的Socket實例并沒有完成創建,而要等到與客戶端的3次握手完成后,這個服務端的Socket實例才會返回,并將這個Socket實例對應的數據結構從未完成列表中移動已完成列表中。
數據傳輸:
當連接已經建立成功時,服務端和客戶端都會擁有一個Socket實例,每個Socket實例都有一個InputStream和OutputStream,并通過這兩個對象來交換數據。
要知道網絡I/O都是以字節流傳輸的,當創建Socket對象時,操作系統將會為InputStream和OutputStream分別分配一定大小的緩存區,數據的寫入和讀取都是通過這個緩存區完成的。
寫入端將數據寫到OutputStream對應的SendQ隊列中,當隊列填滿時,數據將被轉移到另一端InputStream的RecvQ隊列中,如果這時RecvQ已經滿了,那么OutputStream的write方法將會阻塞,直到RecvQ隊列有足夠的空間容納SendQ發送的數據。過程如下圖所示:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。