2022 字
约 6 分钟
9
Java网络编程
2026-09-19
无标签
第64章 Java网络编程
面包屑导航 章节头部 学习目标
学习目标
- 理解网络编程的基本概念和原理
- 掌握Socket编程的基础知识和使用方法
- 学会TCP和UDP协议的区别和应用场景
- 实现客户端和服务器端的通信程序
- 了解网络编程的最佳实践和常见问题
- 掌握多线程网络编程技术
网络编程基础
网络编程基础概念
网络编程是指编写能够在网络上进行数据通信的程序。Java提供了强大的网络编程API,使得开发网络应用变得相对简单。网络编程的核心是Socket(套接字),它是网络通信的端点。
Socket概念
// Socket是网络通信的端点
// 包含IP地址和端口号
// 用于建立网络连接
- 网络通信的基础
- 包含IP地址和端口号
- 支持TCP和UDP协议
- 提供双向数据传输
客户端/服务器模型
// 服务器:监听端口,等待连接
// 客户端:主动连接服务器
// 建立连接后进行数据交换
- 服务器被动等待连接
- 客户端主动发起连接
- 支持多客户端连接
- 可以双向通信
TCP编程
TCP Socket编程
TCP(传输控制协议)是一种可靠的、面向连接的协议。它保证数据的完整性和顺序,适用于对数据准确性要求较高的应用。
TCP服务器端编程
import java.io.*;
import java.net.*;
public class TCPServer {
public static void main(String[] args) {
try {
// 创建服务器Socket,监听8080端口
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器启动,监听端口8080...");
while (true) {
// 等待客户端连接
Socket clientSocket = serverSocket.accept();
System.out.println("客户端连接:" + clientSocket.getInetAddress());
// 创建新线程处理客户端请求
new Thread(new ClientHandler(clientSocket)).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 inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println("收到消息:" + inputLine);
out.println("服务器回复:" + inputLine);
}
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
TCP客户端编程
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class TCPClient {
public static void main(String[] args) {
try {
// 连接到服务器
Socket socket = new Socket("localhost", 8080);
System.out.println("连接到服务器成功!");
// 获取输入输出流
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
Scanner scanner = new Scanner(System.in);
String userInput;
while (true) {
System.out.print("请输入消息(输入'quit'退出):");
userInput = scanner.nextLine();
if ("quit".equalsIgnoreCase(userInput)) {
break;
}
// 发送消息到服务器
out.println(userInput);
// 接收服务器回复
String response = in.readLine();
System.out.println(response);
}
socket.close();
scanner.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UDP编程
UDP Socket编程
UDP(用户数据报协议)是一种无连接的协议,传输速度快但不保证数据的可靠性。适用于对实时性要求较高的应用,如视频流、游戏等。
UDP服务器端编程
import java.net.*;
import java.io.*;
public class UDPServer {
public static void main(String[] args) {
try {
// 创建DatagramSocket,监听9999端口
DatagramSocket socket = new DatagramSocket(9999);
System.out.println("UDP服务器启动,监听端口9999...");
byte[] buffer = new byte[1024];
while (true) {
// 创建数据包接收数据
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
// 获取客户端信息
String message = new String(packet.getData(), 0, packet.getLength());
InetAddress clientAddress = packet.getAddress();
int clientPort = packet.getPort();
System.out.println("收到来自 " + clientAddress + ":" + clientPort + " 的消息:" + message);
// 回复客户端
String response = "服务器收到:" + message;
byte[] responseData = response.getBytes();
DatagramPacket responsePacket = new DatagramPacket(
responseData, responseData.length, clientAddress, clientPort);
socket.send(responsePacket);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
UDP客户端编程
import java.net.*;
import java.io.*;
import java.util.Scanner;
public class UDPClient {
public static void main(String[] args) {
try {
DatagramSocket socket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName("localhost");
int serverPort = 9999;
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("请输入消息(输入'quit'退出):");
String message = scanner.nextLine();
if ("quit".equalsIgnoreCase(message)) {
break;
}
// 发送数据到服务器
byte[] data = message.getBytes();
DatagramPacket packet = new DatagramPacket(
data, data.length, serverAddress, serverPort);
socket.send(packet);
// 接收服务器回复
byte[] buffer = new byte[1024];
DatagramPacket responsePacket = new DatagramPacket(buffer, buffer.length);
socket.receive(responsePacket);
String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
System.out.println(response);
}
socket.close();
scanner.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
协议比较
TCP vs UDP 协议比较
| 特性 | TCP | UDP |
|---|---|---|
| 连接性 | 面向连接 | 无连接 |
| 可靠性 | 可靠传输,保证数据完整性 | 不可靠传输,可能丢失数据 |
| 速度 | 相对较慢 | 快速 |
| 数据顺序 | 保证数据顺序 | 不保证数据顺序 |
| 头部开销 | 20字节 | 8字节 |
| 适用场景 | 文件传输、网页浏览、邮件 | 视频流、游戏、DNS查询 |
高级网络编程
高级网络编程技术
多线程服务器
import java.io.*;
import java.net.*;
import java.util.concurrent.*;
public class ThreadPoolServer {
private static final int PORT = 8080;
private static final int THREAD_POOL_SIZE = 10;
public static void main(String[] args) {
// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
try {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("线程池服务器启动,监听端口" + PORT);
while (true) {
Socket clientSocket = serverSocket.accept();
// 将客户端处理任务提交给线程池
executor.submit(new ClientTask(clientSocket));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
}
}
class ClientTask implements Runnable {
private Socket clientSocket;
public ClientTask(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 inputLine;
while ((inputLine = in.readLine()) != null) {
// 处理客户端请求
String response = processRequest(inputLine);
out.println(response);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String processRequest(String request) {
// 模拟业务处理
return "处理结果:" + request.toUpperCase();
}
}
异常处理和资源管理
public class SafeNetworkClient {
public static void main(String[] args) {
// 使用try-with-resources确保资源正确关闭
try (Socket socket = new Socket("localhost", 8080);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
// 设置超时时间
socket.setSoTimeout(5000); // 5秒超时
out.println("Hello Server");
String response = in.readLine();
System.out.println("服务器回复:" + response);
} catch (SocketTimeoutException e) {
System.err.println("连接超时:" + e.getMessage());
} catch (ConnectException e) {
System.err.println("连接被拒绝:" + e.getMessage());
} catch (IOException e) {
System.err.println("网络错误:" + e.getMessage());
}
}
}
最佳实践
网络编程最佳实践
推荐做法
- 使用try-with-resources管理资源
- 设置合适的超时时间
- 使用线程池处理并发连接
- 正确处理网络异常
- 使用缓冲流提高性能
- 及时关闭网络连接
避免做法
- 忘记关闭Socket连接
- 不处理网络异常
- 在主线程中进行阻塞操作
- 不设置超时时间
- 忽略线程安全问题
- 不验证网络数据
实际应用示例
实际应用示例
简单聊天室应用结合TCP Socket和多线程技术,可以实现一个简单的聊天室应用,支持多用户同时在线聊天。
安全注意事项在实际应用中,需要考虑数据加密、身份验证、防止DOS攻击等安全问题。
性能优化建议
使用NIO(非阻塞I/O)可以进一步提高网络应用的性能和并发处理能力。
代码演示链接 💻 查看完整代码 - 在线IDE体验 章节总结
章节总结
- 网络编程是现代应用开发的重要技能
- Socket是网络通信的基础,包含IP地址和端口号
- TCP协议可靠但相对较慢,适用于数据完整性要求高的场景
- UDP协议快速但不可靠,适用于实时性要求高的场景
- 多线程编程可以提高服务器的并发处理能力
- 正确的异常处理和资源管理是网络编程的关键
- 安全性和性能优化在实际应用中非常重要
导航链接 上一章:Lambda表达式 章节测试 下一章:日志和调试
评论
0 条
还没有评论,先写一条吧。