1. 程式人生 > 實用技巧 >網路安全協議(二)

網路安全協議(二)

一、TCP通訊

  TCP通訊同UDP通訊一樣,都能實現兩臺計算機之間的通訊,通訊的兩端都需要建立socket物件。

  區別在於,UDP中只有傳送端和接收端,不區分客戶端與伺服器端,計算機之間可以任意地傳送資料。

  而TCP通訊是嚴格區分客戶端與伺服器端的,在通訊時,必須先由客戶端去連線伺服器端才能實現通訊,伺服器端不可以主動連線客戶端,並且伺服器端程式需要事先啟動,等待客戶端的連線。

  在JDK中提供了兩個類用於實現TCP程式,一個是ServerSocket類,用於表示伺服器端,一個是Socket類,用於表示客戶端。

  通訊時,首先建立代表伺服器端的ServerSocket物件,該物件相當於開啟一個服務,並等待客戶端的連線,然後建立代表客戶端的Socket物件向伺服器端發出連線請求,伺服器端響應請求,兩者建立連線開始通訊。

1、ServerSocket

  構造方法:

  

  使用該構造方法在建立ServerSocket物件時,就可以將其繫結到一個指定的埠號上(引數port就是埠號)。

  常用方法:

  

2、Socket

  常用構造方法:

  

  使用該構造方法在建立Socket物件時,會根據引數去連線在指定地址和埠上執行的伺服器程式,其中引數host接收的是一個字串型別的IP地址。

  

  該方法在使用上與第二個構造方法類似,引數address用於接收一個InetAddress型別的物件,該物件用於封裝一個IP地址。

   常用方法:

方法宣告

功能描述

int getPort()

該方法返回一個int型別物件,該物件是Socket物件與伺服器端連線的埠號

InetAddressgetLocalAddress()

該方法用於獲取Socket物件繫結的本地IP地址,並將IP地址封裝成InetAddress型別的物件返回

void close()

該方法用於關閉Socket連線,結束本次通訊。在關閉socket之前,應將與socket相關的所有的輸入/輸出流全部關閉,這是因為一個良好的程式應該在執行完畢時釋放所有的資源

InputStream getInputStream()

該方法返回一個InputStream型別的輸入流物件,如果該物件是由

伺服器端的Socket返回,就用於讀取客戶端傳送的資料,反之,用於讀取伺服器端傳送的資料

OutputStream getOutputStream()

該方法返回一個OutputStream型別的輸出流物件,如果該物件是由伺服器端的Socket返回,就用於向客戶端傳送資料,反之,用於向伺服器端傳送資料

二、簡單的TCP網路程式

  要實現TCP通訊需要建立一個伺服器端程式和一個客戶端程式,為了保證資料傳輸的安全性,首先需要實現伺服器端程式。

  

/*
 * 實現TCP 伺服器程式
 * 表示伺服器程式的類 java.net.ServerSocket
 * 構造方法:
 *     ServerSocket(int port)傳遞埠號
 *     很重要的事情:必須要獲得客戶端的套接字物件Socket
 *     Socket accept()
 * 
 * 1,建立伺服器ServerSocket物件(指定伺服器埠號)
 * 2,開啟伺服器了,等待客戶端的連線,當客戶端連線後,可以獲取到連線伺服器的客戶端Socket物件
 * 3,給客戶端反饋資訊
 * 4,關閉流資源
 */
public class TCPServer {
    public static void main(String[] args) throws IOException {
        //1,建立伺服器ServerSocket物件(指定伺服器埠號)
        ServerSocket ss = new ServerSocket(8888);
        //2,開啟伺服器了,等待客戶端的連線,當客戶端連線後,可以獲取到連線伺服器的客戶端Socket物件
        Socket s = ss.accept();
        //3,給客戶端反饋資訊
        /*
         * a,獲取客戶端的輸出流
         * b,在服務端端,通過客戶端的輸出流寫資料給客戶端
         */
        //a,獲取客戶端的輸出流
        OutputStream out = s.getOutputStream();
        //b,在服務端端,通過客戶端的輸出流寫資料給客戶端
        out.write("你已經連線上了伺服器".getBytes());
        //4,關閉流資源
        out.close();
        s.close();
        //ss.close();  伺服器流 通常都是不關閉的
    }
}

完成了伺服器端程式的編寫,接下來編寫客戶端程式。

/*
 * 實現TCP 客戶端,連線到伺服器
 * 和伺服器實現資料交換
 * 實現TCP客戶端程式的類 java.net.Soket
 * 構造方法
 *    Socket(String host,int port) 傳遞伺服器IP和埠號
 *    注意:構造方法只要執行,就會和伺服器進行連線,連線失敗,丟擲異常

 *    OutputStream   getOutputStream() 返回套接字的輸出流
 *    作用:將資料輸出,輸出到伺服器
 *    InputStream   getInputStream() 返回套接字的輸入流
 *    作用:從伺服器端讀取資料

 *    客戶端伺服器資料交換,必須使用套接字物件Socket中的獲取的IO流,自己new流,不行
 
 * 1,建立客戶端Socket物件,(指定要連線的伺服器地址與埠號)
 * 2,獲取伺服器端的反饋回來的資訊
 * 3,關閉流資源
 */
public class TCPClient {
    public static void main(String[] args) throws IOException {
        //1,建立客戶端Socket物件,(指定要連線的伺服器地址與埠號)
        Socket s = new Socket("192.168.74.58", 8888);
        //2,獲取伺服器端的反饋回來的資訊
        InputStream in = s.getInputStream();
        //獲取獲取流中的資料
        byte[] buffer = new byte[1024];
        //把流中的資料儲存到陣列中,並記錄讀取位元組的個數
        int length = in.read(buffer);
        //顯示資料
        System.out.println( new String(buffer, 0 , length) );
        //3,關閉流資源
        in.close();
        s.close();
    }
}

三、檔案上傳案例

首先編寫伺服器端程式,用來接收圖片。

/*
 * TCP上傳伺服器
1.ServerSocket套接字物件,監聽埠8888
2.方法accept()獲取客戶端的連線物件
3.客戶端連線物件獲取位元組輸入流,讀取客戶端傳送圖片
4.建立File物件,繫結上傳資料夾
判斷資料夾存在,不存在,再建立資料夾
5.建立位元組輸出流,資料目的File物件所在資料夾
6.位元組讀取圖片,位元組流將圖片寫入到目的資料夾中
7.將上傳成功返回客戶端
8.關閉資源
 */
public class TCPServer {
    public static void main(String[] args) throws IOException {
        //1,建立伺服器,等待客戶端連線
        ServerSocket serverSocket = new ServerSocket(8888);
        Socket clientSocket = serverSocket.accept();
        //顯示哪個客戶端Socket連線上了伺服器
        InetAddress ipObject = clientSocket.getInetAddress();//得到IP地址物件
        String ip = ipObject.getHostAddress(); //得到IP地址字串
        System.out.println("小樣,抓到你了,連線我!!" + "IP:" + ip);
        
        //7,獲取Socket的輸入流
        InputStream in = clientSocket.getInputStream();
        //8,建立目的地的位元組輸出流   D:\\upload\\192.168.74.58(1).jpg
        BufferedOutputStream fileOut = new BufferedOutputStream(new FileOutputStream("D:\\upload\\192.168.74.58(1).jpg"));
        //9,把Socket輸入流中的資料,寫入目的地的位元組輸出流中
        byte[] buffer = new byte[1024];
        int len = -1;
        while((len = in.read(buffer)) != -1){
            //寫入目的地的位元組輸出流中
            fileOut.write(buffer, 0, len);
        }
        
        //-----------------反饋資訊---------------------
        //10,獲取Socket的輸出流, 作用:寫反饋資訊給客戶端
        OutputStream out = clientSocket.getOutputStream();
        //11,寫反饋資訊給客戶端
        out.write("圖片上傳成功".getBytes());
        
        out.close();
        fileOut.close();
        in.close();
        clientSocket.close();
        //serverSocket.close();
    }
}

編寫客戶端,完成上傳圖片

/*
 * 檔案上傳 客戶端
實現步驟:
1.Socket套接字連線伺服器
2.通過Socket獲取位元組輸出流,寫圖片
3.使用自己的流物件,讀取圖片資料來源
   FileInputStream
4.讀取圖片,使用位元組輸出流,將圖片寫到伺服器
5.通過Socket套接字獲取位元組輸入流
     讀取伺服器發回來的上傳成功
6.關閉資源
 * 
 * public void shutdownOutput()  禁用此Socket的輸出流,間接的相當於告知了伺服器資料寫入完畢
 */
public class TCPClient {
    public static void main(String[] args) throws IOException {
        //2,建立客戶端Socket,連線伺服器
        Socket socket = new Socket("192.168.74.58", 8888);
        //3,獲取Socket流中的輸出流,功能:用來把資料寫到伺服器
        OutputStream out = socket.getOutputStream();
        //4,建立位元組輸入流,功能:用來讀取資料來源(圖片)的位元組
        BufferedInputStream fileIn = new BufferedInputStream(new FileInputStream("D:\\NoDir\\test.jpg"));
        //5,把圖片資料寫到Socket的輸出流中(把資料傳給伺服器)
        byte[] buffer = new byte[1024];
        int len = -1;
        while ((len = fileIn.read(buffer)) != -1){
            //把資料寫到Socket的輸出流中
            out.write(buffer, 0, len);
        }
        //6,客戶端傳送資料完畢,結束Socket輸出流的寫入操作,告知伺服器端
        socket.shutdownOutput();

        //-----------------反饋資訊---------------------
        //12,獲取Socket的輸入流  作用: 讀反饋資訊
        InputStream in = socket.getInputStream();
        //13,讀反饋資訊
        byte[] info = new byte[1024];
        //把反饋資訊儲存到info陣列中,並記錄位元組個數
        int length = in.read(info);
        //顯示反饋結果
        System.out.println( new String(info, 0, length) );
        
        //關閉流
        in.close();
        fileIn.close();
        out.close();
        socket.close();
    }
}