在開發網絡應用程序的時候,會遇到Socket這個概念。
Socket是一個抽象概念,一個應用程序經過一個Socket來創建一個遠程鏈接,而Socket內部經過TCP/IP協議把數據傳輸到網絡。
Socket/TCP/部分IP都是由操做系統提供的。不一樣的編程語言只是提供了對操做系統調用的加單封裝,例如Java提供的幾個Socket相關的類就封裝了操做系統提供的接口。
爲何須要Socket?
由於僅僅經過IP地址進行通訊還不夠,同一臺計算機同一時間會運行多個網絡程序。當計算機收到一個數據包的時候,只有IP地址是無法判斷應該發送給哪一個應用程序的,因此操做系統抽象出Socket接口。每一個應用程序須要對應不一樣的Socket,能夠把Socket簡單理解爲IP地址+端口號。
端口號是操做系統分配的,是在0-65535之間的數字java
Socket編程模型須要實現服務器端與客戶端,由於2個應用程序通訊的時候不只須要對方的IP,還須要知道對方的端口號。因此服務器端必須先固定一個端口號,例如80。客戶端在發起請求的時候,會直接請求80端口,同時告知本身的端口,這樣雙方就能夠經過Socket進行通訊了。
客戶端的編程:編程
Socket sock = new Socket(InetAddress,port);//鏈接到遠程服務器的指定端口 InputStream in = sock.getInputStream();//獲取到輸入和輸出流 OutputStream out = sock.getOutputStream(); //讀寫字節流
服務器端:緩存
ServerSocket ss = new ServerSocket(port); //監聽指定端口號 Socket sock = ss.accept(); InputStream in = sock.getInputStream(); OutputStream out = sock.getOutputStream(); //讀寫字節流
TCPClient.java服務器
import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; public class TCPClient { public static void main(String[] args) throws IOException{ InetAddress addr = InetAddress.getLoopbackAddress(); //獲取本機的InetAddress,一般是127.0.0.1 try(Socket sock = new Socket(addr,9090)){ //打開遠程鏈接 try(BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream(),StandardCharsets.UTF_8))){//BufferedReader類就是一個包裝類,它能夠包裝字符流,將字符流放入緩存裏,到緩存滿了或者執行flush的時候,再讀入內存,能夠提交讀的效率。 try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),StandardCharsets.UTF_8))){ writer.write("time\n"); writer.flush();//強制把緩存區的內容發送出去 String resp = reader.readLine(); System.out.println("Response:"+resp); } } } } }
TCPServer.java網絡
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.time.LocalTime; public class TCPServer { public static void main(String[] args) throws Exception{ ServerSocket ss = new ServerSocket(9090); System.out.println("TCP Server ready:"); Socket sock = ss.accept(); try(BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream(),StandardCharsets.UTF_8))){ try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream(),StandardCharsets.UTF_8))){ String cmd = reader.readLine(); //獲取客戶端傳過來的數據 if("time".equals(cmd)){ writer.write(LocalTime.now()+"\n"); writer.flush(); } } } sock.close(); ss.close(); } }
先運行服務器端,再運行客戶端
socket
TCP編程模型:編程語言