Java網絡編程詳解(三)TCP通信程序

一、什麼是TCP通信?

  • TCP通信能實現兩臺計算機之間的數據交互,通信的兩端,要嚴格區分爲客戶端(Client)與服務器(Server)

二、兩端通信時步驟:

  1. 服務端程序,需要事先啓動,等待客戶端的連接。
  2. 客戶端主動連接服務器端,連接成功才能通信。服務端不可以主動連接客戶端

服務端先啓動
服務器端不會主動的請求客戶端
必須使用客戶端請求服務器端
客戶端和服務端就會建立一個邏輯連接
這個連接中包含一個對象
這個對象就是IO對象
客戶端和服務器端就可以使用
IO對象進行通信
通信的數據不僅僅是字符
所以IO對象是字節流對象

三、在Java中,提供了兩個類用於實現TCP通信程序:

  • 客戶端java.net.Socket類表示。創建Socket對象,向服務端發出連接請求,服務端響應請求,兩者建立連接開始通信。
  • 服務端java.net.ServerSocket類表示。創建ServerSocket對象,相當於開啓一個服務,並等待客戶端的連接。

Socket類:
Socket類:該類實現客戶端套接字,套接字指的是兩臺設備之間通訊的端點
構造方法:
public Socket(String host, int port):創建套接字對象並將其連接到指定主機上的指定端口號。如果指定的host是null,則相當於指定地址爲回送地址。

構造代碼如下:

Socket client = new Socket("127.0.0.1",6666);

四、服務器必須明確兩件事情:

  1. 多個客戶端同時和服務器進行交互,服務器必須明確和哪個客戶端進行的交互。在服務端有一個方法,叫accept客戶端獲取到請求的客戶端對象
  2. 多個客戶端同時和服務器進行交互,就需要使用多個IO流對象

服務器是沒有IO流的,服務器可以獲取到請求的客戶端對象Socket,使用每個客戶端Socket中提供的IO流和客戶端進行交互
服務器使用客戶端的字節輸入流讀取客戶端發送的數據;服務器使用客戶端的字節輸出流給客戶端回寫數據

五、代碼示例詳解

服務端代碼示例:

package Internet;

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. 釋放資源
 */
public class TCPServer {
    public static void main(String[] args) throws IOException {
        //1. 創建服務器ServerSocket對象和系統要指定的端口號
        ServerSocket server = new ServerSocket(9999);
        //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.close();
        server.close();
    }
}

客戶端代碼示例:

package Internet;

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的時候,就會去請求服務器和服務器經過三次握手建立連接通路
            這時如果服務器沒有啓動,那麼就會拋出異常
            如果服務器已經啓動,那麼就可以進行交互了
 */
public class TCPClient {
    public static void main(String[] args) throws IOException {
        //1. 創建一個客戶端對象Socket,構造方法綁定服務器的IP地址和端口號
        Socket socket = new Socket("127.0.0.1",9999);
        //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();
    }
}

運行結果:

現運行服務端,再運行客戶端
在這裏插入圖片描述
在這裏插入圖片描述

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