最近在看dubbo的源代码,看到了org.apache.dubbo.rpc.protocol.tri.TripleProtocol#refer
方法通过exchange->transporter->client的链路获取到了表示客户端连接的Client对象,里面使用到了netty4。因此参考dubbo创建Client的流程写一个netty的示例程序。
服务端搭建
简单使用命令在本地启动一个监听端口的服务端程序:nc -l 30888
我这里监听的30888端口。
客户端搭建
示例代码:
package io.itaiit.netty;
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;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.net.InetSocketAddress;
import java.util.concurrent.ThreadFactory;
/**
* macos系统中简单开启一个监听30888端口的服务:nc -l 30888,运行程序后,接收到客户端发送的消息
*/
public class NettyApp {
// 参考dubbo的代码
public static int DEFAULT_IO_THREADS = Math.min(Runtime.getRuntime().availableProcessors() + 1, 32);
private static EventLoopGroup eventLoopGroup(int threads, String threadFactoryName) {
ThreadFactory threadFactory = new DefaultThreadFactory(threadFactoryName, true);
return new NioEventLoopGroup(threads, threadFactory);
}
private static InetSocketAddress getConnectAddress() {
return new InetSocketAddress("localhost", 30888);
}
public static void main(String[] args) throws InterruptedException {
EventLoopGroup loopGroup = eventLoopGroup(DEFAULT_IO_THREADS, "M-NettyClientWorker");
try {
Bootstrap bootstrap = new Bootstrap();
// 参考dubbo代码:org.apache.dubbo.remoting.transport.netty4.NettyConnectionClient#initBootstrap
bootstrap.group(loopGroup)
.remoteAddress(getConnectAddress())
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
// 添加编解码器
pipeline.addLast(new StringEncoder()); // 将字符串编码为字节
pipeline.addLast(new StringDecoder()); // 将字节解码为字符串
}
});
ChannelFuture localhost = bootstrap.connect().sync();
System.out.println("客户端连接到服务器 127.0.0.1:30888");
Channel channel = localhost.channel();
channel.writeAndFlush("Hello, Netty Server!");
// 等待服务器关闭
localhost.channel().closeFuture().sync();
} finally {
loopGroup.shutdownGracefully();
}
}
}
结果验证
启动客户端程序之后,可以看到服务端成功打印客户端发送的请求:
