網絡編程之TCP協議

tcp協議圖解java

clipboard.png

第二章 TCP通訊程序

2.1 概述

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

兩端通訊時步驟:服務器

  1. 服務端程序,須要事先啓動,等待客戶端的鏈接。
  2. 客戶端主動鏈接服務器端,鏈接成功才能通訊。服務端不能夠主動鏈接客戶端。

在Java中,提供了兩個類用於實現TCP通訊程序:網絡

  1. 客戶端:java.net.Socket 類表示。建立Socket對象,向服務端發出鏈接請求,服務端響應請求,二者創建鏈接開始通訊。
  2. 服務端:java.net.ServerSocket 類表示。建立ServerSocket對象,至關於開啓一個服務,並等待客戶端的鏈接。

2.2 Socket類

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() : 返回此套接字的輸入流。測試

    • 若是此Scoket具備相關聯的通道,則生成的InputStream 的全部操做也關聯該通道。
    • 關閉生成的InputStream也將關閉相關的Socket。
  • public OutputStream getOutputStream() : 返回此套接字的輸出流。spa

    • 若是此Scoket具備相關聯的通道,則生成的OutputStream 的全部操做也關聯該通道。
    • 關閉生成的OutputStream也將關閉相關的Socket。
  • public void close() :關閉此套接字。.net

    • 一旦一個socket被關閉,它不可再使用。
    • 關閉此socket也將關閉相關的InputStream和OutputStream 。
  • public void shutdownOutput() : 禁用此套接字的輸出流。

    • 任何先前寫出的數據將被髮送,隨後終止輸出流。

## 2.3 ServerSocket類

ServerSocket類:這個類實現了服務器套接字,該對象等待經過網絡的請求。

構造方法

  • public ServerSocket(int port) :使用該構造方法在建立ServerSocket對象時,就能夠將其綁定到一個指定的端口號上,參數port就是端口號。

構造舉例,代碼以下:

ServerSocket server = new ServerSocket(6666);

成員方法

  • public Socket accept() :偵聽並接受鏈接,返回一個新的Socket對象,用於和客戶端實現通訊。該方法會一直阻塞直到創建鏈接。

2.4 簡單的TCP網絡程序

TCP通訊分析圖解

  1. 【服務端】啓動,建立ServerSocket對象,等待鏈接。
  2. 【客戶端】啓動,建立Socket對象,請求鏈接。
  3. 【服務端】接收鏈接,調用accept方法,並返回一個Socket對象。
  4. 【客戶端】Socket對象,獲取OutputStream,向服務端寫出數據。
  5. 【服務端】Scoket對象,獲取InputStream,讀取客戶端發送的數據。
到此,客戶端向服務端發送數據成功。

自此,服務端向客戶端回寫數據。
  1. 【服務端】Socket對象,獲取OutputStream,向客戶端回寫數據。
  2. 【客戶端】Scoket對象,獲取InputStream,解析回寫數據。
  3. 【客戶端】釋放資源,斷開鏈接。

客戶端向服務器發送數據

服務端實現:

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();

}

}

相關文章
相關標籤/搜索