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

多线程和线程池的优势

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

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

相关推荐
孤蓬&听雨22 分钟前
Java SpringBoot使用EasyExcel导入导出Excel文件
java·spring boot·excel·导出·导入
散一世繁华,颠半世琉璃23 分钟前
从入门到精通:使用Arthas实现高效的Java问题排查
java·开发语言
ThetaarSofVenice34 分钟前
电影院售票 - 策略模式(Strategy Pattern)
java·设计模式·策略模式
带多刺的玫瑰42 分钟前
Leecode刷题C语言之切蛋糕的最小总开销②
java·数据结构·算法
what_20181 小时前
idea无法安装插件
java·ide·intellij-idea
what_20181 小时前
卸载干净 IDEA(图文讲解)
java·ide·intellij-idea
JavaTestZhangy1 小时前
IDEA试用总结
java·ide·intellij-idea
BUG研究员_1 小时前
微服务のGeteWay
java·数据库·微服务
青冘1 小时前
Java开发 PDF文件生成方案
java·开发语言·pdf
Rk..2 小时前
数据库索引相关总结
java·数据库·sql