From 492a6b1d35c078edc2230b271d3ef7328271ed02 Mon Sep 17 00:00:00 2001 From: Seonghyeon Cho Date: Sun, 14 Apr 2024 19:15:11 +0900 Subject: [PATCH] chapter04 --- chapter04-transport/build.gradle.kts | 10 +++ .../joebrothers/chapter04/NettyNioServer.java | 47 ++++++++++++ .../joebrothers/chapter04/NettyOioServer.java | 47 ++++++++++++ .../joebrothers/chapter04/PlainNioServer.java | 74 +++++++++++++++++++ .../joebrothers/chapter04/PlainOioServer.java | 39 ++++++++++ .../joebrothers/chapter04/package-info.java | 4 + settings.gradle.kts | 1 + 7 files changed, 222 insertions(+) create mode 100644 chapter04-transport/build.gradle.kts create mode 100644 chapter04-transport/src/main/java/com/joebrothers/chapter04/NettyNioServer.java create mode 100644 chapter04-transport/src/main/java/com/joebrothers/chapter04/NettyOioServer.java create mode 100644 chapter04-transport/src/main/java/com/joebrothers/chapter04/PlainNioServer.java create mode 100644 chapter04-transport/src/main/java/com/joebrothers/chapter04/PlainOioServer.java create mode 100644 chapter04-transport/src/main/java/com/joebrothers/chapter04/package-info.java diff --git a/chapter04-transport/build.gradle.kts b/chapter04-transport/build.gradle.kts new file mode 100644 index 0000000..44b5576 --- /dev/null +++ b/chapter04-transport/build.gradle.kts @@ -0,0 +1,10 @@ +plugins { + id("java-conventions") +} + +dependencies { + implementation(project(":core")) + + implementation(platform(libs.netty.bom)) + implementation("io.netty:netty-all") +} diff --git a/chapter04-transport/src/main/java/com/joebrothers/chapter04/NettyNioServer.java b/chapter04-transport/src/main/java/com/joebrothers/chapter04/NettyNioServer.java new file mode 100644 index 0000000..5c2d0d3 --- /dev/null +++ b/chapter04-transport/src/main/java/com/joebrothers/chapter04/NettyNioServer.java @@ -0,0 +1,47 @@ +package com.joebrothers.chapter04; + +import java.net.InetSocketAddress; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.util.CharsetUtil; + +public class NettyNioServer { + public void serve(int port) throws Exception { + final ByteBuf buf = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", CharsetUtil.UTF_8)); + final EventLoopGroup group = new NioEventLoopGroup(); + + try { + final ServerBootstrap b = new ServerBootstrap(); + b.group(group) + .channel(NioServerSocketChannel.class) + .localAddress(new InetSocketAddress(port)) + .childHandler(new ChannelInitializer<>() { + @Override + protected void initChannel(Channel ch) throws Exception { + ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ctx.writeAndFlush(buf.duplicate()) + .addListener(ChannelFutureListener.CLOSE); + } + }); + } + }); + final ChannelFuture f = b.bind().sync(); + f.channel().closeFuture().sync(); + } finally { + group.shutdownGracefully().sync(); + } + } +} diff --git a/chapter04-transport/src/main/java/com/joebrothers/chapter04/NettyOioServer.java b/chapter04-transport/src/main/java/com/joebrothers/chapter04/NettyOioServer.java new file mode 100644 index 0000000..0b66cce --- /dev/null +++ b/chapter04-transport/src/main/java/com/joebrothers/chapter04/NettyOioServer.java @@ -0,0 +1,47 @@ +package com.joebrothers.chapter04; + +import java.net.InetSocketAddress; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.oio.OioEventLoopGroup; +import io.netty.channel.socket.oio.OioServerSocketChannel; +import io.netty.util.CharsetUtil; + +public class NettyOioServer { + public void serve(int port) throws Exception { + final ByteBuf buf = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", CharsetUtil.UTF_8)); + final EventLoopGroup group = new OioEventLoopGroup(); + + try { + final ServerBootstrap b = new ServerBootstrap(); + b.group(group) + .channel(OioServerSocketChannel.class) + .localAddress(new InetSocketAddress(port)) + .childHandler(new ChannelInitializer<>() { + @Override + protected void initChannel(Channel ch) throws Exception { + ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ctx.writeAndFlush(buf.duplicate()) + .addListener(ChannelFutureListener.CLOSE); + } + }); + } + }); + final ChannelFuture f = b.bind().sync(); + f.channel().closeFuture().sync(); + } finally { + group.shutdownGracefully().sync(); + } + } +} diff --git a/chapter04-transport/src/main/java/com/joebrothers/chapter04/PlainNioServer.java b/chapter04-transport/src/main/java/com/joebrothers/chapter04/PlainNioServer.java new file mode 100644 index 0000000..e723625 --- /dev/null +++ b/chapter04-transport/src/main/java/com/joebrothers/chapter04/PlainNioServer.java @@ -0,0 +1,74 @@ +package com.joebrothers.chapter04; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.Iterator; +import java.util.Set; + +public class PlainNioServer { + public void serve(int port) throws IOException { + final ServerSocketChannel serverChannel = ServerSocketChannel.open(); + serverChannel.configureBlocking(false); + + final ServerSocket ssocket = serverChannel.socket(); + final InetSocketAddress address = new InetSocketAddress(port); + ssocket.bind(address); + + final Selector selector = Selector.open(); + serverChannel.register(selector, SelectionKey.OP_ACCEPT); + final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes()); + + for (; ; ) { + try { + selector.select(); + } catch (IOException ex) { + ex.printStackTrace(); + // handle exception + break; + } + + final Set readyKeys = selector.selectedKeys(); + final Iterator iterator = readyKeys.iterator(); + while (iterator.hasNext()) { + final SelectionKey key = iterator.next(); + iterator.remove(); + + try { + if (key.isAcceptable()) { + final ServerSocketChannel server = (ServerSocketChannel) key.channel(); + final SocketChannel client = server.accept(); + client.configureBlocking(false); + client.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, + msg.duplicate()); + System.out.println("Accepted connection from " + client); + } + + if (key.isWritable()) { + final SocketChannel client = (SocketChannel) key.channel(); + final ByteBuffer buffer = (ByteBuffer) key.attachment(); + while (buffer.hasRemaining()) { + if (client.write(buffer) == 0) { + break; + } + } + + client.close(); + } + } catch (IOException ex) { + key.cancel(); + try { + key.channel().close(); + } catch (IOException cex) { + // ignore on close + } + } + } + } + } +} diff --git a/chapter04-transport/src/main/java/com/joebrothers/chapter04/PlainOioServer.java b/chapter04-transport/src/main/java/com/joebrothers/chapter04/PlainOioServer.java new file mode 100644 index 0000000..24f29d6 --- /dev/null +++ b/chapter04-transport/src/main/java/com/joebrothers/chapter04/PlainOioServer.java @@ -0,0 +1,39 @@ +package com.joebrothers.chapter04; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.charset.StandardCharsets; + +public class PlainOioServer { + public void serve(int port) throws IOException { + final ServerSocket socket = new ServerSocket(port); + try { + for (; ; ) { + final Socket clientSocket = socket.accept(); + System.out.println("Accepted connection from" + clientSocket); + + new Thread(() -> { + final OutputStream out; + try { + out = clientSocket.getOutputStream(); + out.write("Hi!\r\n".getBytes(StandardCharsets.UTF_8)); + out.flush(); + clientSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + clientSocket.close(); + } catch (IOException ex) { + // ignore + } + } + }).start(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/chapter04-transport/src/main/java/com/joebrothers/chapter04/package-info.java b/chapter04-transport/src/main/java/com/joebrothers/chapter04/package-info.java new file mode 100644 index 0000000..b979314 --- /dev/null +++ b/chapter04-transport/src/main/java/com/joebrothers/chapter04/package-info.java @@ -0,0 +1,4 @@ +@NonNullByDefault +package com.joebrothers.chapter04; + +import com.joebrothers.annotation.NonNullByDefault; diff --git a/settings.gradle.kts b/settings.gradle.kts index f08e13a..697157c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,5 +12,6 @@ plugins { rootProject.name = "netty-practice" include("core") +include("chapter04-transport") include("echo-client") include("echo-server")