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

        }
    }
}

 

分析:

先運行服務器端代碼,這樣服務器才能工作:打開相應端口,做好接收數據的准備

然后運行客戶端代碼,發送數據

服務器工作時,對應端口一直的打開的,隨時准備響應客戶端的請求

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM