搭建服务器需要什么?
搭建一个 Netty Server需要两个类,一个是启动类,另一个是业务处理类。
先新建一个maven项目,在pom文件里添加 netty 的依赖包,版本为5.0.0
io.netty
netty-all
5.0.0.Alpha1
一、启动类:
public class EchoServer {
private final int port;
public EchoServer(int port)
{
this.port=port;
}
public void start() throws Exception
{
EventLoopGroup group=new NioEventLoopGroup();
try
{
//create ServerBootstrap instance
ServerBootstrap b=new ServerBootstrap();
//Specifies NIO transport,local socket address
//Adds handler to channel pipeline
b.group(group).channel(NioServerSocketChannel.class).localAddress(port) // 这里告诉Channel如何接收新的连接
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) throws Exception
{
// 自定义处理类
ch.pipeline().addLast(new EchoServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
// 绑定端口,开始接收进来的连接
ChannelFuture f = b.bind(port).sync();
System.out.println(EchoServer.class.getName()+" started and listen on "+f.channel().localAddress());
// 等待服务器socket关闭
f.channel().closeFuture().sync();
}catch (Exception e){
System.out.println(e);
}
finally {
group.shutdownGracefully().sync();
}
}
public static void main(String[] agrs)throws Exception
{
System.out.println("Server_star");
new EchoServer(8001).start();
System.out.println("Server_end");
}
}
二、业务处理类:
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception
{
System.out.println("客户端连上...");
}
@Override
public void channelRead(ChannelHandlerContext ctx,Object msg) throws Exception
{
try {
ByteBuf in = (ByteBuf) msg;
System.out.println( new Date().toString() );
System.out.println("收到的:"+in.toString(CharsetUtil.UTF_8));
ctx.write(Unpooled.copiedBuffer("你好, I am server!", CharsetUtil.UTF_8));
ctx.flush();
}catch (Exception e){
System.out.println("异常"+e);
}finally {
ReferenceCountUtil.release(msg);
}
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception
{
try {
ctx.flush();
}catch (Exception e){
System.out.println("异常"+e);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception
{
System.out.println("exceptionCaught:"+ctx);
cause.printStackTrace();
ctx.close();
}
}
三、测试搭建是否成功
我们可以去自定义客户端程序,这里为了方便使用 telnet 充当客户端。需要注意的是,Windows 默认是没有开启 telnet 客户端的,需要我们手动开启。菜单->控制面板->程序->打开或关闭Windows功能,设置如图:
设置完成后,启动运行服务端的程序EchoServer,在 cmd 窗口输入命令如下: telnet + ip + 端口号
进入如下界面 ,即连接成功
同时控制台输出连接情况
接下来,输入一个字符,比如'a' ,telnet实时发送该字符给服务端(如果telnet 窗口看不到输入的字符,只要输入 ctrl+L 就可以看到输入的字符了)。控制台打印收到的客户端数据,并发送一条应答信息:Hello,I am client!
telnet客户端:收到来自服务端的数据
上述测试方法,每输入一个字符都会当成一次通讯过程。如果想从客户端发送一段完整的数据,可以在客户端输入 Ctrl+]
使用telnet 的send命令发送数据,如下图。这样就可以发送一整段信息。
服务端收到的数据:
以上步骤跑通后,说明服务端已搭建成功。
搭建一个 Netty Client 同样也需要两个类,一个是启动类,另一个是业务处理类。
一、启动类
public class EchoClient {
private final String host;
private final int 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(host,port))
.handler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel ch) throws Exception
{
ch.pipeline().addLast(new EchoClientHandler());
}
});
Channel channel = b.connect().sync().channel();
channel.closeFuture().sync();
}finally {
group.shutdownGracefully().sync();
}
}
public static void main(String[] agrs) throws Exception
{
System.out.println("client_star");
new EchoClient("localhost",8001).start();
}
}
二、业务处理类
public class EchoClientHandler extends SimpleChannelInboundHandler {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception
{
System.out.println("服务端连上了");
ctx.write(Unpooled.copiedBuffer("Hello, I am client!", Charset.forName("UTF-8")));
ctx.flush();
}
@Override
public void messageReceived(ChannelHandlerContext ctx,ByteBuf msg)throws Exception{
try {
System.out.println( new Date().toString() );
System.out.println("Client Received!: "+ msg.toString(CharsetUtil.UTF_8));
}catch (Exception e){
System.out.println("异常"+e);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception
{
cause.printStackTrace();
ctx.close();
}
}
一、启动运行服务端的程序EchoServer
二、启动运行客户端的程序EchoClient