java—网络编程TCP和UDP

1. Java 网络编程概述

Java 网络编程是通过 java.net 包实现的,Socket 类是用来进行客户端与服务器通信的主要类。服务器端通过 ServerSocket 类来监听客户端的请求,客户端则通过 Socket 类来连接服务器。

2. TCP 网络编程示例

TCP 通信中,数据传输是可靠的,确保了数据的顺序和完整性。以下是一个简单的客户端和服务器应用,其中服务器端监听指定端口,客户端向服务器发送消息并接收响应。

2.1 TCP 服务器端
复制代码
import java.io.*;
import java.net.*;

public class TCPServer {
    public static void main(String[] args) {
        try {
            // 创建ServerSocket对象,监听端口12345
            ServerSocket serverSocket = new ServerSocket(12345);
            System.out.println("Server is listening on port 12345...");

            while (true) {
                // 等待客户端连接
                Socket clientSocket = serverSocket.accept();
                System.out.println("New client connected: " + clientSocket.getInetAddress());

                // 创建线程来处理客户端请求
                Thread clientThread = new Thread(new ClientHandler(clientSocket));
                clientThread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class ClientHandler implements Runnable {
    private Socket clientSocket;

    public ClientHandler(Socket socket) {
        this.clientSocket = socket;
    }

    @Override
    public void run() {
        try {
            // 获取客户端输入和输出流
            BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);

            // 读取客户端发送的消息
            String message = in.readLine();
            System.out.println("Received from client: " + message);

            // 发送响应给客户端
            out.println("Hello from server!");

            // 关闭连接
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
2.2 TCP 客户端
复制代码
import java.io.*;
import java.net.*;

public class TCPClient {
    public static void main(String[] args) {
        try {
            // 创建Socket对象连接到服务器
            Socket socket = new Socket("localhost", 12345);
            System.out.println("Connected to the server");

            // 获取输入输出流
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            // 向服务器发送消息
            out.println("Hello from client!");

            // 接收服务器响应
            String response = in.readLine();
            System.out.println("Received from server: " + response);

            // 关闭连接
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行步骤

  1. 先启动 TCPServer,它将监听端口 12345。
  2. 然后启动 TCPClient,它将连接到服务器并发送消息。

输出示例

  • 服务器端

    复制代码
    Server is listening on port 12345...
    New client connected: /127.0.0.1
    Received from client: Hello from client!
  • 客户端

    复制代码
    Connected to the server
    Received from server: Hello from server!

3. UDP 网络编程示例

UDP 是一种无连接、不保证可靠性的协议,适用于实时性要求高,但对数据丢失不敏感的场景(如视频流、在线游戏等)。

3.1 UDP 服务器端
复制代码
import java.net.*;

public class UDPServer {
    public static void main(String[] args) {
        try {
            // 创建UDP服务器端套接字
            DatagramSocket serverSocket = new DatagramSocket(12345);
            System.out.println("UDP Server is listening on port 12345...");

            byte[] receiveData = new byte[1024];

            while (true) {
                // 创建数据报包来接收客户端消息
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                serverSocket.receive(receivePacket);

                // 获取客户端地址和数据
                String clientMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());
                System.out.println("Received from client: " + clientMessage);

                // 发送响应给客户端
                InetAddress clientAddress = receivePacket.getAddress();
                int clientPort = receivePacket.getPort();
                String responseMessage = "Hello from UDP server!";
                DatagramPacket sendPacket = new DatagramPacket(responseMessage.getBytes(), responseMessage.length(), clientAddress, clientPort);
                serverSocket.send(sendPacket);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
3.2 UDP 客户端

import java.net.*;

public class UDPClient {

public static void main(String[] args) {

try {

// 创建UDP客户端套接字

DatagramSocket clientSocket = new DatagramSocket();

InetAddress serverAddress = InetAddress.getByName("localhost");

// 发送消息给服务器

String message = "Hello from UDP client!";

DatagramPacket sendPacket = new DatagramPacket(message.getBytes(), message.length(), serverAddress, 12345);

clientSocket.send(sendPacket);

// 接收服务器的响应

byte[] receiveData = new byte[1024];

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

clientSocket.receive(receivePacket);

// 显示服务器响应

String response = new String(receivePacket.getData(), 0, receivePacket.getLength());

System.out.println("Received from server: " + response);

// 关闭客户端套接字

clientSocket.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

运行步骤

  1. 先启动 UDPServer,它将监听端口 12345。
  2. 然后启动 UDPClient,它将向服务器发送消息并接收响应。

输出示例

  • 服务器端

    复制代码
    UDP Server is listening on port 12345...
    Received from client: Hello from UDP client!
  • 客户端

    复制代码
    Received from server: Hello from UDP server!

4. 多线程和线程池示例

为了处理多个客户端的连接,可以使用 多线程 来为每个客户端创建独立的处理线程。此外,使用 线程池 可以有效地管理线程,提高服务器的性能。

4.1 使用线程池管理客户端请求

(1)线程池版的 TCP 服务器

复制代码
import java.io.*;
import java.net.*;
import java.util.concurrent.*;

public class ThreadPoolTCPServer {
    private static final int PORT = 12345;

    public static void main(String[] args) {
        try {
            // 创建线程池
            ExecutorService threadPool = Executors.newFixedThreadPool(10);

            // 创建ServerSocket并监听端口
            ServerSocket serverSocket = new ServerSocket(PORT);
            System.out.println("Server is listening on port " + PORT);

            while (true) {
                // 接受客户端连接
                Socket clientSocket = serverSocket.accept();
                System.out.println("New client connected: " + clientSocket.getInetAddress());

                // 将客户端连接交给线程池处理
                threadPool.submit(new ClientHandler(clientSocket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class ClientHandler implements Runnable {
        private Socket clientSocket;

        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }

        @Override
        public void run() {
            try {
                // 获取输入输出流
                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);

                // 处理客户端请求
                String message = in.readLine();
                System.out.println("Received from client: " + message);
                out.println("Hello from server!");

                // 关闭连接
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

多线程和线程池的优势

  • 使用 线程池 可以避免频繁创建和销毁线程,从而提升性能。
  • 每个客户端连接都会分配一个线程,线程池确保了线程的复用。

++喜欢这期内容的话,别忘了点个赞,关注博主,这样就不会错过任何更新啦!还有,收藏一下,方便以后回顾哦!++

相关推荐
写bug写bug11 分钟前
手把手教你使用JConsole
java·后端·程序员
异常君13 分钟前
Java 中 try-catch 的性能真相:全面分析与最佳实践
java·面试·代码规范
程序员清风1 小时前
阿里二面:Kafka 消费者消费消息慢(10 多分钟),会对 Kafka 有什么影响?
java·后端·面试
幼稚园的山代王1 小时前
Prompt Enginering(提示工程)先进技术
java·人工智能·ai·chatgpt·langchain·prompt
周某某~1 小时前
二.单例模式‌
java·单例模式·设计模式
摸鱼仙人~1 小时前
深入理解Java单例模式:确保类只有一个实例
java·javascript·单例模式
hstar95271 小时前
三十五、面向对象底层逻辑-Spring MVC中AbstractXlsxStreamingView的设计
java·后端·spring·设计模式·架构·mvc
pengyu2 小时前
【Java设计原则与模式之系统化精讲:壹】 | 编程世界的道与术(实战指导篇)
java·后端·设计模式
日月星辰Ace2 小时前
JVM 垃圾回收简介
java
掉头发的王富贵2 小时前
Arthas神器入门:动态调试Java应用,轻松搞定生产环境Bug!
java·后端·debug