2019独角兽企业重金招聘Python工程师标准>>>
霸王硬上,直接开始,服务端:
package com.hengzenc.NettyServer;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg){
ctx.write(msg);
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){
cause.printStackTrace();ctx.close();
}
}
- DiscardServerHandler继承了ChannelInboundHandlerAdapter,而不是直接实现父类ChannelInboundHandler,因为ChannelInboundHandlerAdapter已经够用了。
- 我们覆盖了channelRead()方法,这个方法在收到信息的时候调用。
- 这里使用的ByteBuf必须进行显示地进行关闭。
- exceptionCaught关闭链接的时候,通常应当首先给客户端发送一个错误消息。
现在我们用main()方法来启动DiscardServerHandler的服务器
package com.hengzenc.NettyServer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class DiscardServer {
private int port;
public DiscardServer(int port) {
this.port = port;
}
public void run() throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // (3)
.childHandler(new ChannelInitializer() { // (4)
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DiscardServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128) // (5)
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
// Bind and start to accept incoming connections.
ChannelFuture f = b.bind(port).sync(); // (7)
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
f.channel().closeFuture().sync();
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new DiscardServer(port).run();
}
}
- 我们在这里使用了两个NioEventLoopGroup来处理I/O操作,第一个叫做boss,接收链接请求;第二个叫做worker,在boss接受了请求之后向worker注册。具体使用多少线程取决于EventLoopGroup的实现。
2. ServerBootstrap是建立服务器的帮助类。你可以直接使用Channel来建立服务器。不过请注意这是个无聊的过程,在大多数情况下不要这样用。
3. 我们在这里使用NioServerSocketChannel来初始新的Channel来接收请求。
4. 这里指定的handler经常被新Channel评估。ChannelInitializer是帮助用户配置新Channel的特定handler。
5. 我们在这里是实现一个TCP/IP服务器,我们使用了tcpNoDelay和keepAlive,至于其它的选项,请到ChannelOption和ChannelConfig里面去查找。
6. option是给接受请求的NioServerSocketChannel的,childOption是给父ServerChannel接受的Channel,在这里是NioServerSocketChannel。
7. 绑定端口,启动服务器。
上一篇写好了一个服务器,可以在本地使用telnet localhost 8080来测试这个服务器,这个服务器只是简单地回复你发给它的信息,如下图所示: