一、网络编程基础概念
1.1 网络协议分层模型
Java网络编程主要基于TCP/IP协议栈,理解分层模型至关重要:
- OSI七层模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
- TCP/IP四层模型:网络接口层、网络层、传输层、应用层
- Java主要涉及的层次:传输层(TCP/UDP)和应用层(HTTP/FTP等)
1.2 关键网络概念
- IP地址:设备的网络标识(IPv4/IPv6)
- 端口号:0-65535,标识主机上的特定服务
- Socket:网络通信的端点,IP地址+端口号
- 协议:TCP(可靠连接)和UDP(无连接)
二、Java网络编程核心API
2.1 Java.net包核心类
// TCP相关
Socket // 客户端Socket
ServerSocket // 服务端Socket
// UDP相关
DatagramSocket
DatagramPacket
// URL处理
URL
URLConnection
HttpURLConnection
2.2 NIO包(New I/O)
ByteBuffer
Channel // SocketChannel, ServerSocketChannel
Selector // 多路复用选择器
Charset // 字符编码处理
三、TCP编程实战
3.1 基础TCP通信实现
服务端代码示例:
import java.io.*;
import java.net.*;
public class TCPServer {
public static void main(String[] args) throws IOException {
// 1. 创建ServerSocket,监听指定端口
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务器启动,等待客户端连接...");
// 2. 接受客户端连接
Socket clientSocket = serverSocket.accept();
System.out.println("客户端连接成功:" + clientSocket.getInetAddress());
// 3. 获取输入输出流
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(
clientSocket.getOutputStream(), true);
// 4. 通信循环
String request;
while ((request = in.readLine()) != null) {
System.out.println("收到客户端消息:" + request);
String response = "服务器响应:" + request.toUpperCase();
out.println(response);
}
// 5. 关闭资源
clientSocket.close();
serverSocket.close();
}
}
客户端代码示例:
import java.io.*;
import java.net.*;
public class TCPClient {
public static void main(String[] args) throws IOException {
// 1. 创建Socket连接服务器
Socket socket = new Socket("localhost", 8888);
// 2. 获取输入输出流
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
// 3. 用户输入处理
BufferedReader userInput = new BufferedReader(
new InputStreamReader(System.in));
System.out.println("请输入消息(输入exit退出):");
String userMsg;
while ((userMsg = userInput.readLine()) != null) {
if ("exit".equalsIgnoreCase(userMsg)) break;
// 4. 发送消息并接收响应
out.println(userMsg);
String response = in.readLine();
System.out.println("服务器响应:" + response);
}
// 5. 关闭连接
socket.close();
}
}
3.2 多线程TCP服务器
处理多个客户端连接:
import java.io.*;
import java.net.*;
public class MultiThreadTCPServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("多线程服务器启动...");
while (true) {
Socket clientSocket = serverSocket.accept();
new ClientHandler(clientSocket).start();
}
}
static class ClientHandler extends Thread {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try (
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true)
) {
String clientAddress = socket.getInetAddress().toString();
System.out.println("处理客户端连接:" + clientAddress);
String request;
while ((request = in.readLine()) != null) {
System.out.println(clientAddress + " 发送: " + request);
out.println("ECHO: " + request);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
四、UDP编程实战
4.1 基础UDP通信
服务端代码:
import java.net.*;
public class UDPServer {
public static void main(String[] args) throws Exception {
// 1. 创建DatagramSocket,指定端口
DatagramSocket socket = new DatagramSocket(8888);
System.out.println("UDP服务器启动...");
byte[] buffer = new byte[1024];
while (true) {
// 2. 创建接收包
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// 3. 接收数据
socket.receive(packet);
// 4. 处理数据
String received = new String(
packet.getData(), 0, packet.getLength());
System.out.println("收到来自 " + packet.getAddress() +
":" + packet.getPort() + " 的消息: " + received);
// 5. 准备响应
String response = "UDP响应: " + received.toUpperCase();
byte[] responseData = response.getBytes();
// 6. 发送响应
DatagramPacket responsePacket = new DatagramPacket(
responseData, responseData.length,
packet.getAddress(), packet.getPort());
socket.send(responsePacket);
}
}
}
客户端代码:
import java.net.*;
import java.util.Scanner;
public class UDPClient {
public static void main(String[] args) throws Exception {
// 1. 创建DatagramSocket
DatagramSocket socket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName("localhost");
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("请输入消息(输入exit退出): ");
String message = scanner.nextLine();
if ("exit".equalsIgnoreCase(message)) break;
// 2. 准备发送包
byte[] sendData = message.getBytes();
DatagramPacket sendPacket = new DatagramPacket(
sendData, sendData.length, serverAddress, 8888);
// 3. 发送数据
socket.send(sendPacket);
// 4. 准备接收响应
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(
receiveData, receiveData.length);
// 5. 接收响应
socket.receive(receivePacket);
// 6. 处理响应
String response = new String(
receivePacket.getData(), 0, receivePacket.getLength());
System.out.println("服务器响应: " + response);
}
socket.close();
scanner.close();
}
}
五、Java NIO编程
5.1 NIO核心组件
- Buffer:数据容器
- Channel:数据传输通道
- Selector:多路复用器
5.2 NIO服务器示例
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;
public class NIOServer {
public static void main(String[] args) throws IOException {
// 1. 创建Selector
Selector selector = Selector.open();
// 2. 创建ServerSocketChannel并配置为非阻塞
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.bind(new InetSocketAddress(8888));
serverSocket.configureBlocking(false);
// 3. 注册到Selector,关注ACCEPT事件
serverSocket.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("NIO服务器启动...");
while (true) {
// 4. 阻塞等待就绪的Channel
selector.select();
// 5. 获取就绪的SelectionKey集合
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
// 6. 处理ACCEPT事件
if (key.isAcceptable()) {
handleAccept(serverSocket, selector);
}
// 7. 处理READ事件
if (key.isReadable()) {
handleRead(key);
}
iter.remove();
}
}
}
private static void handleAccept(ServerSocketChannel serverSocket,
Selector selector) throws IOException {
// 接受客户端连接
SocketChannel client = serverSocket.accept();
client.configureBlocking(false);
// 注册到Selector,关注READ事件
client.register(selector, SelectionKey.OP_READ);
System.out.println("客户端连接: " + client.getRemoteAddress());
}
private static void handleRead(SelectionKey key) throws IOException {
SocketChannel client = (SocketChannel) key.channel();
// 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
try {
// 读取数据
int bytesRead = client.read(buffer);
if (bytesRead == -1) {
// 连接关闭
System.out.println("客户端断开: " + client.getRemoteAddress());
client.close();
return;
}
// 处理数据
buffer.flip();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
String received = new String(bytes);
System.out.println("收到消息: " + received);
// 准备响应
String response = "NIO响应: " + received.toUpperCase();
ByteBuffer responseBuffer = ByteBuffer.wrap(response.getBytes());
// 发送响应
client.write(responseBuffer);
} catch (IOException e) {
System.out.println("客户端异常断开: " + client.getRemoteAddress());
client.close();
}
}
}
5.3 NIO客户端示例
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
public class NIOClient {
public static void main(String[] args) throws IOException {
// 1. 创建SocketChannel
SocketChannel socketChannel = SocketChannel.open();
// 2. 连接服务器
socketChannel.connect(new InetSocketAddress("localhost", 8888));
System.out.println("连接到服务器...");
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("请输入消息(输入exit退出): ");
String message = scanner.nextLine();
if ("exit".equalsIgnoreCase(message)) break;
// 3. 发送消息
ByteBuffer writeBuffer = ByteBuffer.wrap(message.getBytes());
socketChannel.write(writeBuffer);
// 4. 接收响应
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int bytesRead = socketChannel.read(readBuffer);
if (bytesRead > 0) {
readBuffer.flip();
byte[] bytes = new byte[readBuffer.remaining()];
readBuffer.get(bytes);
String response = new String(bytes);
System.out.println("服务器响应: " + response);
}
}
socketChannel.close();
scanner.close();
}
}
六、高级网络编程技术
6.1 非阻塞IO与异步IO
- Java NIO:非阻塞IO,基于选择器(Selector)模式
- Java AIO:异步IO(Asynchronous IO),基于回调机制
6.2 Netty框架简介
Netty是基于NIO的客户端/服务器框架,简化了网络编程:
// Netty服务器简单示例
public class NettyServer {
public static void main(String[] args) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new EchoServerHandler());
}
});
ChannelFuture future = bootstrap.bind(8888).sync();
future.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}
// 处理器
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ctx.write(msg); // 回显收到的消息
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
6.3 HTTP客户端实现
使用Java原生API实现HTTP请求:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpClientExample {
public static void main(String[] args) throws Exception {
String url = "http://example.com";
// 1. 创建URL对象
URL obj = new URL(url);
// 2. 打开连接
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// 3. 设置请求方法
con.setRequestMethod("GET");
// 4. 添加请求头
con.setRequestProperty("User-Agent", "Java HTTPClient");
// 5. 获取响应码
int responseCode = con.getResponseCode();
System.out.println("响应码: " + responseCode);
// 6. 读取响应
try (BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()))) {
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
// 7. 打印响应
System.out.println("响应内容:");
System.out.println(response.toString());
}
}
}
七、网络编程最佳实践
-
资源管理:
- 使用try-with-resources确保资源关闭
- 正确处理异常和连接断开情况
-
性能优化:
- 使用连接池管理TCP连接
- 合理设置缓冲区大小
- 考虑使用NIO或Netty处理高并发
-
安全考虑:
- 使用SSL/TLS加密通信
- 验证输入数据防止注入攻击
- 实现适当的认证和授权机制
-
错误处理:
- 处理各种网络异常(ConnectException, SocketTimeoutException等)
- 实现重试机制处理临时性故障
八、常见问题与解决方案
8.1 连接超时问题
解决方案:
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host, port), 5000); // 5秒超时
8.2 处理粘包/拆包问题
解决方案:
- 使用固定长度消息
- 使用特殊分隔符
- 在消息头添加长度字段
8.3 高并发连接管理
解决方案:
- 使用线程池管理连接
- 考虑NIO或Netty等高性能框架
- 实现连接超时和心跳机制
九、总结
Java网络编程涵盖了从基础的Socket通信到高级的NIO和Netty框架:
- TCP/UDP编程:理解两种协议的特点和适用场景
- NIO编程:掌握非阻塞IO和多路复用技术
- 高级框架:了解Netty等网络框架的优势
- 最佳实践:遵循资源管理、性能优化和安全原则
网络编程是Java开发中的重要技能,希望本文能帮助您深入理解其原理并掌握实战技巧。在实际开发中,应根据具体需求选择合适的网络编程方式和框架。
4803

被折叠的 条评论
为什么被折叠?



