tcp協議圖解java
TCP通訊能實現兩臺計算機之間的數據交互,通訊的兩端,要嚴格區分爲客戶端(Client)與服務端(Server)。數組
兩端通訊時步驟:服務器
在Java中,提供了兩個類用於實現TCP通訊程序:網絡
java.net.Socket
類表示。建立Socket
對象,向服務端發出鏈接請求,服務端響應請求,二者創建鏈接開始通訊。java.net.ServerSocket
類表示。建立ServerSocket
對象,至關於開啓一個服務,並等待客戶端的鏈接。Socket
類:該類實現客戶端套接字,套接字指的是兩臺設備之間通信的端點。socket
public Socket(String host, int port)
:建立套接字對象並將其鏈接到指定主機上的指定端口號。若是指定的host是null ,則至關於指定地址爲回送地址。tcp
小貼士:回送地址(127.x.x.x) 是本機回送地址(Loopback Address),主要用於網絡軟件測試以及本地機進程間通訊,不管什麼程序,一旦使用回送地址發送數據,當即返回,不進行任何網絡傳輸。
構造舉例,代碼以下:oop
Socket client = new Socket("127.0.0.1", 6666);
public InputStream getInputStream()
: 返回此套接字的輸入流。測試
public OutputStream getOutputStream()
: 返回此套接字的輸出流。spa
public void close()
:關閉此套接字。.net
public void shutdownOutput()
: 禁用此套接字的輸出流。
## 2.3 ServerSocket類
ServerSocket
類:這個類實現了服務器套接字,該對象等待經過網絡的請求。
public ServerSocket(int port)
:使用該構造方法在建立ServerSocket對象時,就能夠將其綁定到一個指定的端口號上,參數port就是端口號。構造舉例,代碼以下:
ServerSocket server = new ServerSocket(6666);
public Socket accept()
:偵聽並接受鏈接,返回一個新的Socket對象,用於和客戶端實現通訊。該方法會一直阻塞直到創建鏈接。到此,客戶端向服務端發送數據成功。
自此,服務端向客戶端回寫數據。
服務端實現:
public class ServerTCP { public static void main(String[] args) throws IOException { System.out.println("服務端啓動 , 等待鏈接 .... "); // 1.建立 ServerSocket對象,綁定端口,開始等待鏈接 ServerSocket ss = new ServerSocket(6666); // 2.接收鏈接 accept 方法, 返回 socket 對象. Socket server = ss.accept(); // 3.經過socket 獲取輸入流 InputStream is = server.getInputStream(); // 4.一次性讀取數據 // 4.1 建立字節數組 byte[] b = new byte[1024]; // 4.2 據讀取到字節數組中. int len = is.read(b); // 4.3 解析數組,打印字符串信息 String msg = new String(b, 0, len); System.out.println(msg); //5.關閉資源. is.close(); server.close(); } }
客戶端實現:
public class ClientTCP { public static void main(String[] args) throws Exception { System.out.println("客戶端 發送數據"); // 1.建立 Socket ( ip , port ) , 肯定鏈接到哪裏. Socket client = new Socket("localhost", 6666); // 2.獲取流對象 . 輸出流 OutputStream os = client.getOutputStream(); // 3.寫出數據. os.write("你好麼? tcp ,我來了".getBytes()); // 4. 關閉資源 . os.close(); client.close(); } }
服務端實現:
public class ServerTCP { public static void main(String[] args) throws IOException { System.out.println("服務端啓動 , 等待鏈接 .... "); // 1.建立 ServerSocket對象,綁定端口,開始等待鏈接 ServerSocket ss = new ServerSocket(6666); // 2.接收鏈接 accept 方法, 返回 socket 對象. Socket server = ss.accept(); // 3.經過socket 獲取輸入流 InputStream is = server.getInputStream(); // 4.一次性讀取數據 // 4.1 建立字節數組 byte[] b = new byte[1024]; // 4.2 據讀取到字節數組中. int len = is.read(b); // 4.3 解析數組,打印字符串信息 String msg = new String(b, 0, len); System.out.println(msg); // =================回寫數據======================= // 5. 經過 socket 獲取輸出流 OutputStream out = server.getOutputStream(); // 6. 回寫數據 out.write("我很好,謝謝你".getBytes()); // 7.關閉資源. out.close(); is.close(); server.close(); } }
客戶端實現:
public class ClientTCP { public static void main(String[] args) throws Exception { System.out.println("客戶端 發送數據"); // 1.建立 Socket ( ip , port ) , 肯定鏈接到哪裏. Socket client = new Socket("localhost", 6666); // 2.經過Scoket,獲取輸出流對象 OutputStream os = client.getOutputStream(); // 3.寫出數據. os.write("你好麼? tcp ,我來了".getBytes()); // ==============解析回寫========================= // 4. 經過Scoket,獲取 輸入流對象 InputStream in = client.getInputStream(); // 5. 讀取數據數據 byte[] b = new byte[100]; int len = in.read(b); System.out.println(new String(b, 0, len)); // 6. 關閉資源 . in.close(); os.close(); client.close(); } }
如下是實際代碼
package com.itheima.demo01.TCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/*
TCP通訊的服務器端:接收客戶端的請求,讀取客戶端發送的數據,給客戶端回寫數據 表示服務器的類: java.net.ServerSocket:此類實現服務器套接字。 構造方法: ServerSocket(int port) 建立綁定到特定端口的服務器套接字。 服務器端必須明確一件事情,必須的知道是哪一個客戶端請求的服務器 因此可使用accept方法獲取到請求的客戶端對象Socket 成員方法: Socket accept() 偵聽並接受到此套接字的鏈接。 服務器的實現步驟: 1.建立服務器ServerSocket對象和系統要指定的端口號 2.使用ServerSocket對象中的方法accept,獲取到請求的客戶端對象Socket 3.使用Socket對象中的方法getInputStream()獲取網絡字節輸入流InputStream對象 4.使用網絡字節輸入流InputStream對象中的方法read,讀取客戶端發送的數據 5.使用Socket對象中的方法getOutputStream()獲取網絡字節輸出流OutputStream對象 6.使用網絡字節輸出流OutputStream對象中的方法write,給客戶端回寫數據 7.釋放資源(Socket,ServerSocket)
*/
public class TCPServer {
public static void main(String[] args) throws IOException { //1.建立服務器ServerSocket對象和系統要指定的端口號 ServerSocket server = new ServerSocket(8888); //2.使用ServerSocket對象中的方法accept,獲取到請求的客戶端對象Socket Socket socket = server.accept(); //3.使用Socket對象中的方法getInputStream()獲取網絡字節輸入流InputStream對象 InputStream is = socket.getInputStream(); //4.使用網絡字節輸入流InputStream對象中的方法read,讀取客戶端發送的數據 byte[] bytes = new byte[1024]; int len = is.read(bytes); System.out.println(new String(bytes,0,len)); //5.使用Socket對象中的方法getOutputStream()獲取網絡字節輸出流OutputStream對象 OutputStream os = socket.getOutputStream(); //6.使用網絡字節輸出流OutputStream對象中的方法write,給客戶端回寫數據 os.write("收到謝謝".getBytes()); //7.釋放資源(Socket,ServerSocket) socket.close(); server.close(); }
}
package com.itheima.demo01.TCP;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/*
TCP通訊的客戶端:向服務器發送鏈接請求,給服務器發送數據,讀取服務器回寫的數據 表示客戶端的類: java.net.Socket:此類實現客戶端套接字(也能夠就叫「套接字」)。套接字是兩臺機器間通訊的端點。 套接字:包含了IP地址和端口號的網絡單位 構造方法: Socket(String host, int port) 建立一個流套接字並將其鏈接到指定主機上的指定端口號。 參數: String host:服務器主機的名稱/服務器的IP地址 int port:服務器的端口號 成員方法: OutputStream getOutputStream() 返回此套接字的輸出流。 InputStream getInputStream() 返回此套接字的輸入流。 void close() 關閉此套接字。 實現步驟: 1.建立一個客戶端對象Socket,構造方法綁定服務器的IP地址和端口號 2.使用Socket對象中的方法getOutputStream()獲取網絡字節輸出流OutputStream對象 3.使用網絡字節輸出流OutputStream對象中的方法write,給服務器發送數據 4.使用Socket對象中的方法getInputStream()獲取網絡字節輸入流InputStream對象 5.使用網絡字節輸入流InputStream對象中的方法read,讀取服務器回寫的數據 6.釋放資源(Socket) 注意: 1.客戶端和服務器端進行交互,必須使用Socket中提供的網絡流,不能使用本身建立的流對象 2.當咱們建立客戶端對象Socket的時候,就會去請求服務器和服務器通過3次握手創建鏈接通路 這時若是服務器沒有啓動,那麼就會拋出異常ConnectException: Connection refused: connect 若是服務器已經啓動,那麼就能夠進行交互了
*/
public class TCPClient {
public static void main(String[] args) throws IOException { //1.建立一個客戶端對象Socket,構造方法綁定服務器的IP地址和端口號 Socket socket = new Socket("127.0.0.1",8888); //2.使用Socket對象中的方法getOutputStream()獲取網絡字節輸出流OutputStream對象 OutputStream os = socket.getOutputStream(); //3.使用網絡字節輸出流OutputStream對象中的方法write,給服務器發送數據 os.write("你好服務器".getBytes()); //4.使用Socket對象中的方法getInputStream()獲取網絡字節輸入流InputStream對象 InputStream is = socket.getInputStream(); //5.使用網絡字節輸入流InputStream對象中的方法read,讀取服務器回寫的數據 byte[] bytes = new byte[1024]; int len = is.read(bytes); System.out.println(new String(bytes,0,len)); //6.釋放資源(Socket) socket.close(); }
}