1. 程式人生 > >TCP和UDP套接字程式設計 (java實現)

TCP和UDP套接字程式設計 (java實現)

在瞭解網路程式設計之前,我們先了解一下什麼叫套接字

套接字即指同一臺主機內應用層和運輸層之間的介面

由於這個套接字是建立在網路上建立網路應用的可程式設計介面

因此也將套接字稱為應用程式和網路之間的應用程式程式設計介面!

 

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

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

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

TCP套接字程式設計:

 客戶端:

package TCP套接字程式設計;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

public class TCPClient {
    public
static void main(String[] args) throws UnknownHostException, IOException { // 建立兩個String型別的字串用來接收和傳送字元 String sentence; String modifiedSentence; // 建立輸入流,用來接收鍵盤輸入 BufferedReader inFromUser = new BufferedReader(new InputStreamReader( System.in));
// 建立一個Scoket型的clientScoket用來發起伺服器和客戶機之間的連線 String postname = "169.264.187.20";// 客戶端ip地址(請用自己電腦的ip地址代替) Socket clientSocket = new Socket(postname, 6789); // 建立向伺服器傳送資訊的輸出流 DataOutputStream outToServer = new DataOutputStream( clientSocket.getOutputStream()); // 建立輸入流,用來接收來自伺服器的位元組流 BufferedReader inFromServer = new BufferedReader(new InputStreamReader( clientSocket.getInputStream())); // 讀取要傳送的資料 sentence = inFromUser.readLine(); // 向伺服器傳送資料 outToServer.writeBytes(sentence + '\n'); // 獲取從伺服器接收的資料 modifiedSentence = inFromServer.readLine(); // 列印接收資料 System.out.println("From Server:" + modifiedSentence); } }

伺服器端:

package TCP套接字程式設計;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {
    public static void main(String[] args) throws IOException {
        // 從客戶端接收的字串,要傳送給客戶端的字串
        String clientSentence;
        String serverSentence;

        // 伺服器開啟6789埠,建立連線
        ServerSocket welcomeSocket = new ServerSocket(6789);

        while (true) {// 伺服器的6789埠一直開啟

            // 用此連線來獲取和傳送客戶端資料流
            Socket connectionSocket = welcomeSocket.accept();

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

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

            // 讀取收到的資料
            clientSentence = inFromClient.readLine();

            // 將讀取到的資料都中的小寫字母改為大寫字母
            serverSentence = clientSentence.toUpperCase() + '\n';

            // 傳送修改後的資料給客戶端
            outToClient.writeBytes(serverSentence);

        }
    }
}

UDP套接字程式設計:

客戶端:

package UDP套接字程式設計;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

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

        // 為客戶端創造一個傳輸資訊的門,但是並沒有像TCP那樣建立連線
        DatagramSocket clientSocket = new DatagramSocket();

        // 呼叫DNS查詢,得到主機名對應的IP地址
        InetAddress IPAddress = InetAddress.getByName(null);//null的話得到的是自己的IP地址
        System.out.println(IPAddress);

        // 定義需要傳送的位元組陣列
        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, 9878);

        // 用這個門來發送資料報
        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 + '\n');

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

    }

}

伺服器端:

package UDP套接字程式設計;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

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

        // 建立一個門,在9878埠
        DatagramSocket serverSocket = new DatagramSocket(9878);

        while (true) {

            // 定義接收資料的位元組陣列
            byte[] receiveData = new byte[1024];

            // 定義傳送資料的位元組陣列
            byte[] sendData = new byte[1024];

            // 建立UDP資料報物件,準備接收UDP資料報
            DatagramPacket receivePacket = new DatagramPacket(receiveData,
                    receiveData.length);

            // 接收UDP資料報
            serverSocket.receive(receivePacket);

            // 將收到的UDP資料報轉換為String字串
            String sentence = new String(receivePacket.getData());

            // 得到接收到的UDP資料報的源IP地址
            InetAddress IPAddress = receivePacket.getAddress();

            // 得到接收到的UDP資料報的源埠號
            int port = receivePacket.getPort();

            // 小寫字母全部變為大寫字母
            String capitalized = sentence.toUpperCase();

            // 將字串轉換為位元組陣列以便傳送
            sendData = capitalized.getBytes();

            // 準備傳送位元組陣列,做好封裝UDP資料報工作
            DatagramPacket sendPacket = new DatagramPacket(sendData,
                    sendData.length, IPAddress, port);

            // 通過門正式傳送UDP資料報
            serverSocket.send(sendPacket);

        }
    }
}

 

分析:

先執行伺服器端程式碼,這樣伺服器才能工作:開啟相應埠,做好接收資料的準備

然後執行客戶端程式碼,傳送資料

伺服器工作時,對應埠一直的開啟的,隨時準備響應客戶端的請求

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