Nettyを使ってクライアントを実装してみた

# 初めに
前回は[Nettyを使ってサーバーを作りました](https://qiita.com/haoyu_ma/items/e1989ae752500521825b)が、今日は引き続きクライアント側も実装してみます。

# 実装

➀アクセスの生成や終了などの処理

```java

public class EchoClient {
    private final String host;
    private final int port;

    public EchoClient() {
        this(0);
    }

    public EchoClient(int port) {
        this("localhost", port);
    }

    public EchoClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void start() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .remoteAddress(new InetSocketAddress(this.host, this.port))
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            System.out.println("connected...");
                            ch.pipeline().addLast(new EchoClientHandler());
                        }
                    });
            System.out.println("created..");

            ChannelFuture cf = b.connect().sync();
            System.out.println("connected...");

            cf.channel().closeFuture().sync();
            System.out.println("closed..");
        } finally {
            group.shutdownGracefully().sync();
        }
    }

    public static void main(String[] args) throws Exception {
        new EchoClient("127.0.0.1", 31535).start();
    }
}

```

②タイミングによるを起動された関数（callbackはず）

- channelActive() - サーバーへの接続がクリエイトされた時
- channelRead0() - サーバー側がデータを貰った時
- exceptionCaught() - レラーが感知された時

```java

public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("client channelActive..");
        ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        System.out.println("client channelRead..");
        ByteBuf buf = msg.readBytes(msg.readableBytes());
        System.out.println("Client received:" + ByteBufUtil.hexDump(buf) + "; The value is:" + buf.toString(Charset.forName("utf-8")));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

}

```

# 結果認証
**サーバーを起動し、接続を待ち受け中**

```
class EchoServer started and listen on /0:0:0:0:0:0:0:0:31535
```

**サーバーを起動し、サーバーにリクエストします**
**クライアントとサーバーそれぞれの出力は以下になります**

- クライアント

```
created..
connected...
client channelActive..
connected...
client channelRead..
Client received:4e6574747920726f636b7321; The value is:Netty rocks!
closed..

Process finished with exit code 0
```

- サーバー

```
class EchoServer started and listen on /0:0:0:0:0:0:0:0:31535
connected...; Client:/127.0.0.1:56967
server channelRead...; received:PooledUnsafeDirectByteBuf(ridx: 0, widx: 12, cap: 1024)
server channelReadComplete..
```


# まとめ
今回はNettyを使ってNIOの転送路を作ってみました、ServerSocketChannelやSocketChannelなのに比べて、低レベルのAPIを書く必要がなく、楽になりました。