第494集网络编程
|字数总计:3.8k|阅读时长:19分钟|阅读量:
网络编程
1. 概述
1.1 网络编程的重要性
网络编程是Java开发中的重要技能,涉及Socket编程、TCP/UDP通信、NIO、Netty等核心技术,是构建分布式系统的基础。
本文内容:
- 网络基础:TCP/IP协议、Socket概念
- Socket编程:TCP和UDP Socket编程
- NIO:非阻塞IO和选择器
- Netty框架:高性能网络框架
- HTTP客户端:HTTP请求处理
- 实战案例:网络编程实战
1.2 本文内容结构
本文将从以下几个方面深入探讨网络编程:
- 网络基础:TCP/IP协议和网络模型
- Socket编程:TCP和UDP Socket
- NIO编程:非阻塞IO和选择器
- Netty框架:Netty的使用和原理
- HTTP编程:HTTP客户端和服务器
- 实战案例:网络编程实战
2. 网络基础
2.1 TCP/IP协议
2.1.1 协议栈
TCP/IP协议栈:
1 2 3 4 5
| 应用层 HTTP, FTP, SMTP, DNS 传输层 TCP, UDP 网络层 IP, ICMP, ARP 数据链路层 以太网, WiFi 物理层 网线, 光纤
|
TCP vs UDP:
| 特性 |
TCP |
UDP |
| 连接 |
面向连接 |
无连接 |
| 可靠性 |
可靠传输 |
不可靠传输 |
| 速度 |
较慢 |
较快 |
| 适用场景 |
文件传输、Web |
视频、游戏 |
2.2 Socket概念
2.2.1 Socket简介
Socket:网络通信的端点,是IP地址和端口号的组合。
Socket通信流程:
1 2 3 4 5 6 7 8 9 10 11
| 服务器端: 1. 创建ServerSocket,绑定端口 2. 监听客户端连接 3. 接受连接,创建Socket 4. 通过Socket进行通信 5. 关闭连接
客户端: 1. 创建Socket,连接服务器 2. 通过Socket进行通信 3. 关闭连接
|
3. Socket编程
3.1 TCP Socket
3.1.1 TCP服务器
TCP服务器示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| import java.io.*; import java.net.*;
public class TCPServer { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server started on port 8888"); while (true) { Socket clientSocket = serverSocket.accept(); System.out.println("Client connected: " + clientSocket.getRemoteSocketAddress()); new Thread(() -> { try { handleClient(clientSocket); } catch (IOException e) { e.printStackTrace(); } }).start(); } } catch (IOException e) { e.printStackTrace(); } } private static void handleClient(Socket socket) throws IOException { try { BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream()) ); PrintWriter out = new PrintWriter( socket.getOutputStream(), true ); String message; while ((message = in.readLine()) != null) { System.out.println("Received: " + message); out.println("Echo: " + message); if ("bye".equalsIgnoreCase(message)) { break; } } } finally { socket.close(); System.out.println("Client disconnected"); } } }
|
3.1.2 TCP客户端
TCP客户端示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import java.io.*; import java.net.*;
public class TCPClient { public static void main(String[] args) { try { Socket socket = new Socket("localhost", 8888); System.out.println("Connected to server"); BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream()) ); PrintWriter out = new PrintWriter( socket.getOutputStream(), true ); BufferedReader userInput = new BufferedReader( new InputStreamReader(System.in) ); String userMessage; while ((userMessage = userInput.readLine()) != null) { out.println(userMessage); String response = in.readLine(); System.out.println("Server: " + response); if ("bye".equalsIgnoreCase(userMessage)) { break; } } socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
|
3.2 UDP Socket
3.2.1 UDP服务器
UDP服务器示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import java.net.*;
public class UDPServer { public static void main(String[] args) { try { DatagramSocket socket = new DatagramSocket(8888); System.out.println("UDP Server started on port 8888"); 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()); System.out.println("Received: " + message + " from " + packet.getSocketAddress()); String response = "Echo: " + message; byte[] responseData = response.getBytes(); DatagramPacket responsePacket = new DatagramPacket( responseData, responseData.length, packet.getSocketAddress() ); socket.send(responsePacket); } } catch (IOException e) { e.printStackTrace(); } } }
|
3.2.2 UDP客户端
UDP客户端示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| import java.net.*; 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 = 8888; Scanner scanner = new Scanner(System.in); while (true) { System.out.print("Enter message: "); String message = scanner.nextLine(); 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("Server: " + response); if ("bye".equalsIgnoreCase(message)) { break; } } socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
|
3.3 多线程服务器
3.3.1 线程池服务器
使用线程池的TCP服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| import java.io.*; import java.net.*; import java.util.concurrent.*;
public class ThreadPoolTCPServer { private static final int PORT = 8888; private static final int THREAD_POOL_SIZE = 10; public static void main(String[] args) { ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE); try { ServerSocket serverSocket = new ServerSocket(PORT); System.out.println("Server started on port " + PORT); while (true) { Socket clientSocket = serverSocket.accept(); System.out.println("Client connected: " + clientSocket.getRemoteSocketAddress()); threadPool.submit(() -> { try { handleClient(clientSocket); } catch (IOException e) { e.printStackTrace(); } }); } } catch (IOException e) { e.printStackTrace(); } finally { threadPool.shutdown(); } } private static void handleClient(Socket socket) throws IOException { try (BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter( socket.getOutputStream(), true)) { String message; while ((message = in.readLine()) != null) { System.out.println("Received: " + message); out.println("Echo: " + message); if ("bye".equalsIgnoreCase(message)) { break; } } } finally { socket.close(); System.out.println("Client disconnected"); } } }
|
4. NIO编程
4.1 NIO基础
4.1.1 NIO核心组件
NIO核心组件:
- Channel(通道):数据读写通道
- Buffer(缓冲区):数据容器
- Selector(选择器):多路复用器
NIO vs BIO:
| 特性 |
BIO |
NIO |
| 阻塞 |
阻塞IO |
非阻塞IO |
| 线程模型 |
一个连接一个线程 |
一个线程处理多个连接 |
| 性能 |
较低 |
较高 |
| 适用场景 |
连接数少 |
连接数多 |
4.2 Channel和Buffer
4.2.1 Channel使用
Channel示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import java.io.*; import java.nio.*; import java.nio.channels.*;
public class ChannelExample { public void fileChannelExample() throws IOException { RandomAccessFile file = new RandomAccessFile("test.txt", "rw"); FileChannel channel = file.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); buffer.put("Hello NIO".getBytes()); buffer.flip(); channel.write(buffer); buffer.clear(); channel.read(buffer); buffer.flip(); byte[] data = new byte[buffer.remaining()]; buffer.get(data); System.out.println(new String(data)); channel.close(); file.close(); } }
|
4.2.2 Buffer使用
Buffer示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import java.nio.*;
public class BufferExample { public void bufferExample() { ByteBuffer buffer = ByteBuffer.allocate(1024); buffer.put("Hello".getBytes()); buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } buffer.clear(); } }
|
4.3 Selector
4.3.1 多路复用
Selector示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| import java.io.*; import java.net.*; import java.nio.*; import java.nio.channels.*; import java.util.*;
public class NIOSelectorServer { public static void main(String[] args) { try { ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.bind(new InetSocketAddress(8888)); serverChannel.configureBlocking(false); Selector selector = Selector.open(); serverChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("NIO Server started on port 8888"); while (true) { int readyChannels = selector.select(); if (readyChannels == 0) continue; Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key.isAcceptable()) { handleAccept(key, selector); } else if (key.isReadable()) { handleRead(key); } keyIterator.remove(); } } } catch (IOException e) { e.printStackTrace(); } } private static void handleAccept(SelectionKey key, Selector selector) throws IOException { ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel(); SocketChannel clientChannel = serverChannel.accept(); clientChannel.configureBlocking(false); clientChannel.register(selector, SelectionKey.OP_READ); System.out.println("Client connected: " + clientChannel.getRemoteAddress()); } private static void handleRead(SelectionKey key) throws IOException { SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = channel.read(buffer); if (bytesRead > 0) { buffer.flip(); byte[] data = new byte[buffer.remaining()]; buffer.get(data); String message = new String(data); System.out.println("Received: " + message); buffer.clear(); buffer.put(("Echo: " + message).getBytes()); buffer.flip(); channel.write(buffer); } else if (bytesRead < 0) { channel.close(); System.out.println("Client disconnected"); } } }
|
5. Netty框架
5.1 Netty基础
5.1.1 Netty简介
Netty:高性能、异步事件驱动的网络框架。
Netty优势:
- 高性能:基于NIO,性能优异
- 易用性:API简单,易于使用
- 稳定性:久经考验,稳定可靠
- 功能丰富:支持多种协议
5.2 Netty服务器
5.2.1 Netty服务器示例
Netty服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder;
public class NettyServer { private static final int PORT = 8888; public static void main(String[] args) throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(1); 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) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new StringDecoder()); pipeline.addLast(new StringEncoder()); pipeline.addLast(new NettyServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture future = bootstrap.bind(PORT).sync(); System.out.println("Netty Server started on port " + PORT); future.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }
class NettyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { String message = (String) msg; System.out.println("Received: " + message); ctx.writeAndFlush("Echo: " + message); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } @Override public void channelActive(ChannelHandlerContext ctx) { System.out.println("Client connected: " + ctx.channel().remoteAddress()); } @Override public void channelInactive(ChannelHandlerContext ctx) { System.out.println("Client disconnected: " + ctx.channel().remoteAddress()); } }
|
5.3 Netty客户端
5.3.1 Netty客户端示例
Netty客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder;
public class NettyClient { private static final String HOST = "localhost"; private static final int PORT = 8888; public static void main(String[] args) throws InterruptedException { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new StringDecoder()); pipeline.addLast(new StringEncoder()); pipeline.addLast(new NettyClientHandler()); } }); ChannelFuture future = bootstrap.connect(HOST, PORT).sync(); System.out.println("Connected to server"); Channel channel = future.channel(); channel.writeAndFlush("Hello Netty"); channel.closeFuture().sync(); } finally { group.shutdownGracefully(); } } }
class NettyClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { String message = (String) msg; System.out.println("Server: " + message); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } }
|
5.4 Netty编解码器
5.4.1 自定义编解码器
自定义编解码器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.MessageToByteEncoder;
import java.util.List;
public class CustomDecoder extends ByteToMessageDecoder { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) { if (in.readableBytes() < 4) { return; } int length = in.readInt(); if (in.readableBytes() < length) { in.resetReaderIndex(); return; } byte[] data = new byte[length]; in.readBytes(data); String message = new String(data); out.add(message); } }
public class CustomEncoder extends MessageToByteEncoder<String> { @Override protected void encode(ChannelHandlerContext ctx, String msg, ByteBuf out) { byte[] data = msg.getBytes(); out.writeInt(data.length); out.writeBytes(data); } }
|
6. HTTP编程
6.1 HTTP客户端
6.1.1 Java原生HTTP客户端
Java 11+ HTTP客户端:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import java.net.http.*; import java.net.URI; import java.time.Duration;
public class HttpClientExample { public void httpGetExample() throws Exception { HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://www.example.com")) .GET() .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println("Status: " + response.statusCode()); System.out.println("Body: " + response.body()); } public void httpPostExample() throws Exception { HttpClient client = HttpClient.newHttpClient(); String json = "{\"name\":\"test\"}"; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.example.com/data")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(json)) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println("Response: " + response.body()); } }
|
6.2 HTTP服务器
6.2.1 简单HTTP服务器
使用Netty的HTTP服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.*;
public class HttpServer { private static final int PORT = 8080; public static void main(String[] args) throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(1); 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) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpObjectAggregator(65536)); pipeline.addLast(new HttpServerHandler()); } }); ChannelFuture future = bootstrap.bind(PORT).sync(); System.out.println("HTTP Server started on port " + PORT); future.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }
class HttpServerHandler extends SimpleChannelInboundHandler<FullHttpRequest> { @Override protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) { String uri = request.uri(); String method = request.method().name(); System.out.println("Method: " + method + ", URI: " + uri); FullHttpResponse response = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.OK ); String content = "Hello from HTTP Server"; response.content().writeBytes(content.getBytes()); response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain"); response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.length()); ctx.writeAndFlush(response); } }
|
7. 实战案例
7.1 聊天室服务器
7.1.1 多客户端聊天室
使用Netty实现聊天室:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; import io.netty.util.concurrent.GlobalEventExecutor;
public class ChatServer { private static final int PORT = 8888; private static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); public static void main(String[] args) throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(1); 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) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new StringDecoder()); pipeline.addLast(new StringEncoder()); pipeline.addLast(new ChatServerHandler()); } }); ChannelFuture future = bootstrap.bind(PORT).sync(); System.out.println("Chat Server started on port " + PORT); future.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } static class ChatServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) { channels.add(ctx.channel()); String message = "User " + ctx.channel().remoteAddress() + " joined"; channels.writeAndFlush(message); System.out.println(message); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { String message = (String) msg; String sender = ctx.channel().remoteAddress().toString(); String broadcast = "[" + sender + "] " + message; channels.writeAndFlush(broadcast); System.out.println(broadcast); } @Override public void channelInactive(ChannelHandlerContext ctx) { channels.remove(ctx.channel()); String message = "User " + ctx.channel().remoteAddress() + " left"; channels.writeAndFlush(message); System.out.println(message); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } } }
|
7.2 文件传输
7.2.1 文件上传下载
文件传输示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.stream.ChunkedWriteHandler;
public class FileTransferServer { public static void main(String[] args) throws InterruptedException { EventLoopGroup bossGroup = new NioEventLoopGroup(1); 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) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new ChunkedWriteHandler()); pipeline.addLast(new FileTransferHandler()); } }); ChannelFuture future = bootstrap.bind(8888).sync(); System.out.println("File Transfer Server started"); future.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }
|
8. 总结
8.1 核心要点
- Socket编程:TCP和UDP Socket是网络编程基础
- NIO:非阻塞IO提高性能,适合高并发场景
- Netty:高性能网络框架,简化网络编程
- HTTP编程:HTTP客户端和服务器实现
8.2 关键理解
- BIO vs NIO:BIO阻塞,NIO非阻塞,NIO性能更高
- Netty优势:基于NIO,API简单,性能优异
- 线程模型:合理使用线程池,避免线程过多
- 编解码:正确处理数据编解码,避免数据丢失
8.3 最佳实践
- 使用Netty:优先使用Netty进行网络编程
- 合理配置:根据场景配置线程数和缓冲区大小
- 异常处理:完善的异常处理机制
- 资源管理:及时关闭连接和释放资源
相关文章: