1. 程式人生 > >JavaTCP和UDP套接字程式設計

JavaTCP和UDP套接字程式設計

在我們剛開始入門Java後端的時候可能你會覺得有點複雜,包含了很多雜七雜八的知識,例如檔案上傳下載,監聽器,JDBC,請求重定向,請求轉發等等(當然也沒有很多),但是我們自己真正的去開發一個小型網站(對安全性一起其他併發不作要求)的時候,其實我們會發現,Java後端是真的省事,好像除了CURD還是CURD,沒有什麼更新鮮的了。但是我們回顧計算機網路的知識提出疑問,計算機資訊傳輸有TCP和UDP兩種連線方式,但是我們程式設計的時候怎麼沒體現?怎麼回事呢?

我們學JavaWeb的時候估計最熟悉的就是Servlet了,但是追下去其實我們寫的後端Servlet只是實現了一個介面,並沒有在裡面實現什麼方法,且剛開始程式設計的時候,總會到Tomcat資料夾下複製一個Jar包到專案中,我們的專案才可以執行,否則會報錯是不是,所以我們大概可以推測出對於一些網路連線和傳輸都是Tomcat幫我們做了,也就是伺服器幫我們做了,那麼我們在實際的編碼中怎麼通過Java來實現計算機之間的通訊呢?
Java也為我們考慮到了,Java的網路程式設計,也叫作Socket程式設計!

在瞭解網路程式設計之前,我們先了解一下什麼叫套接字,套接字即指同一臺主機內應用層和運輸層之間的介面,由於這個套接字是建立在網路上建立網路應用的可程式設計介面,因此也將套接字稱為應用程式和網路之間的應用程式程式設計介面!
這裡寫圖片描述

關於TCP和UDP這裡就不作太多介紹了,我們知道TCP是面向連線的,UDP是不面向連線的,TCP可靠,UDP不可靠即可!
我們來設計一個應用來示範一下,流程:

  1. 客戶機從鍵盤讀取一行字串,並通過套接字傳送到伺服器。
  2. 伺服器從連線的套接字獲取這行字串,並對其進行修改(將小寫轉為大寫),最後再發回客戶端。
  3. 客戶機讀取到伺服器傳送的修改後的字串,並輸出到螢幕。

不說太多了,直接上程式碼:

TCPClient:

public class TCPClient {
    public static void main(String[] args) throws Exception {
        //建立兩個String型別的字串用來發送和接受
        String sentence;
        String modifiedSentence;

        //建立輸入流,用來接受鍵盤輸入
        BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in
)); //建立一個Socket型別的 clientSocket 用來發起伺服器和客戶機之間的連線 Socket clientSocket = new Socket("hostname",6789); //建立向伺服器傳送資訊的輸出流 DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); //建立輸入流,用來接收來自伺服器的位元組流 BufferedReader inFormServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); //讀流資料 sentence = inFromUser.readLine(); //向伺服器傳送sentence的位元組資料 outToServer.writeBytes(sentence + '\n'); //獲取位元組流資料為String modifiedSentence = inFormServer.readLine(); System.out.println("Form Server :" + modifiedSentence); } }

TCPServer:

public class TCPServer {
    public static void main(String[] args) throws Exception{
        String clientSentence;
        String capitalizedSentence;

        //伺服器Socket用來建立連線
        ServerSocket welcomeSocket = new ServerSocket(6789);

        while(true){

            //用這個連線來獲取和傳送,自客戶端發的資料流
            Socket connectionSocket = welcomeSocket.accept();

            //獲取來自客戶端的位元組流
            BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));

            //傳送更改後的資料流
            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());

            //讀取位元組成String字串
            clientSentence = inFromClient.readLine();

            capitalizedSentence = clientSentence.toUpperCase() +'\n';

            outToClient.writeBytes(capitalizedSentence);
        }   
    }
}
public class UDPClient {
    public static void main(String[] args) throws Exception{
        //讀取鍵盤輸入的位元組流
        BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));

        //為客戶機建立了一個傳輸資訊的門,但是並沒與向TCP那樣建立連線
        DatagramSocket clientSocket = new DatagramSocket();

        //這行程式碼呼叫了DNS查詢,查詢主機名對應的IP地址,後面要用這個地址來向伺服器傳送資訊
        InetAddress IPAddress = InetAddress.getByName("hostname");

        //需要傳送的位元組陣列
        byte[] sendData = new byte[1024];

        //接受的位元組陣列
        byte[] receiveData = new byte[1024];

        String sentence = inFromUser.readLine();

        //將字串轉為位元組放入sendData
        sendData = sentence.getBytes();

        //UDP資料報分組,裡面包含想要傳送的內容以及目的地址等資訊
        DatagramPacket sendPacket = new DatagramPacket(sendData,sendData.length,IPAddress,9876);

        //用這個‘門’來發送這個資料包
        clientSocket.send(sendPacket);

        //獲取資料報分組
        DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length);

        //用‘門’獲取資料報
        clientSocket.receive(receivePacket);

        //將獲取的資料報轉為String型別資料
        String modifiedSentence = new String(receivePacket.getData());

        System.out.println("From Server:" + modifiedSentence);

        //關閉這個門
        clientSocket.close();

    }
}
public class UDPServer {
    public static void main(String[] args) throws Exception{

        //大意和客戶端程式碼類似
        DatagramSocket serverSocket = new DatagramSocket(9876);

        byte[] receiveData = new byte[1024];

        byte[] sendData = new byte[1024];

        while(true){

            DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length);

            serverSocket.receive(receivePacket);

            String sentence = new String(receivePacket.getData());

            InetAddress IPAddress = receivePacket.getAddress();

            int port = receivePacket.getPort();

            String capitalized = sentence.toUpperCase();

            sendData = capitalized.getBytes();

            DatagramPacket sendPacket = new DatagramPacket(sendData,sendData.length,IPAddress,port);

            serverSocket.send(sendPacket);
        }
    }
}

有網路基本常識的朋友應該很好理解上面的程式碼(記錄供以後參考),博主在程式碼中也作了很詳細的註釋,這裡就不在多解釋什麼了,相信通過上面簡單的例子,我們能夠了解Java是如何實現TCP和UDP套接字程式設計。

以上程式碼參考《計算機網路自頂向下方法》,其他為博主的一些粗陋的見解,可能有不全面的地方,如果大神見到,還請賜教!

參考書籍:《計算機網路自頂向下方法》