基於socket的netty demo
阿新 • • 發佈:2019-02-14
和http不一樣,http可以用瀏覽器來充當客戶端呼叫,所以基於socket的netty,必須要編寫客戶端和伺服器的程式碼
實現功能:
客戶端給伺服器發訊息,伺服器給客戶端回訊息
一直迴圈
伺服器程式碼
package com.bill.socketdemo; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; public class SocketServer { public static void main(String[] args) throws Exception { // 這2個group都是死迴圈,阻塞式 EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class). childHandler(new SocketServerInitializer()); ChannelFuture channelFuture = serverBootstrap.bind(8899).sync(); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }
package com.bill.socketdemo; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import java.util.UUID; public class SocketServerHandler extends SimpleChannelInboundHandler<String> { /** * 讀取客戶端請求,並且返回給客戶端資料的方法 */ @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println(ctx.channel().remoteAddress() + ", " + msg); ctx.channel().writeAndFlush("from server:" + UUID.randomUUID()); } /** * 處理異常的方法,一旦出現異常,就會呼叫此方法 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
package com.bill.socketdemo; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import io.netty.handler.codec.LengthFieldPrepender; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.util.CharsetUtil; public class SocketServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast("LengthFieldBasedFrameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); pipeline.addLast("LengthFieldPrepender",new LengthFieldPrepender(4)); pipeline.addLast("StringDecoder",new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast("StringEncoder",new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast("SocketServerHandler", new SocketServerHandler()); } }
客戶端程式碼
package com.bill.socketdemo;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
public class SocketClient {
public static void main(String[] args) throws Exception {
// 這2個group都是死迴圈,阻塞式
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).
handler(new SocketClientInitializer());
ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync();
channelFuture.channel().closeFuture().sync();
} finally {
eventLoopGroup.shutdownGracefully();
}
}
}
package com.bill.socketdemo;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import java.util.UUID;
public class SocketClientHandler extends SimpleChannelInboundHandler<String> {
/**
* 傳送內容給伺服器端
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(ctx.channel().remoteAddress());
System.out.println("client output:" + msg);
ctx.writeAndFlush("from client:" + UUID.randomUUID());
}
/**
* 該方法向伺服器發資料,打破伺服器-客戶端一直等待對方發資料的僵局
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush("from client: hello world");
}
/**
* 處理異常的方法,一旦出現異常,就會呼叫此方法
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
package com.bill.socketdemo;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
public class SocketClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast("LengthFieldBasedFrameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
pipeline.addLast("LengthFieldPrepender",new LengthFieldPrepender(4));
pipeline.addLast("StringDecoder",new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast("StringEncoder",new StringEncoder(CharsetUtil.UTF_8));
pipeline.addLast("SocketServerHandler", new SocketClientHandler());
}
}
執行結果
先執行伺服器:
再執行客戶端:
執行完客戶端後伺服器的情況
完整程式碼下載: