基于socket的netty demo
阅读原文时间:2023年07月08日阅读:4

前面一文说了 基于http的netty demo

和http不一样,http可以用浏览器来充当客户端调用,所以基于socket的netty,必须要编写客户端和服务器的代码

实现功能:

客户端给服务器发消息,服务器给客户端回消息

一直循环

1 package com.bill.socketdemo;
2
3
4 import io.netty.bootstrap.ServerBootstrap;
5 import io.netty.channel.ChannelFuture;
6 import io.netty.channel.EventLoopGroup;
7 import io.netty.channel.nio.NioEventLoopGroup;
8 import io.netty.channel.socket.nio.NioServerSocketChannel;
9
10 public class SocketServer {
11
12 public static void main(String[] args) throws Exception {
13
14 // 这2个group都是死循环,阻塞式
15 EventLoopGroup bossGroup = new NioEventLoopGroup();
16 EventLoopGroup workerGroup = new NioEventLoopGroup();
17
18 try {
19 ServerBootstrap serverBootstrap = new ServerBootstrap();
20 serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).
21 childHandler(new SocketServerInitializer());
22
23 ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
24 channelFuture.channel().closeFuture().sync();
25 } finally {
26 bossGroup.shutdownGracefully();
27 workerGroup.shutdownGracefully();
28 }
29 }
30
31 }
32
33 package com.bill.socketdemo;
34
35 import io.netty.channel.ChannelHandlerContext;
36 import io.netty.channel.SimpleChannelInboundHandler;
37
38 import java.util.UUID;
39
40 public class SocketServerHandler extends SimpleChannelInboundHandler {
41
42 /**
43 * 读取客户端请求,并且返回给客户端数据的方法
44 */
45 @Override
46 protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
47 System.out.println(ctx.channel().remoteAddress() + ", " + msg);
48 ctx.channel().writeAndFlush("from server:" + UUID.randomUUID());
49 }
50
51 /**
52 * 处理异常的方法,一旦出现异常,就会调用此方法
53 */
54 @Override
55 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
56 cause.printStackTrace();
57 ctx.close();
58 }
59 }
60
61 package com.bill.socketdemo;
62
63 import io.netty.channel.ChannelInitializer;
64 import io.netty.channel.ChannelPipeline;
65 import io.netty.channel.socket.SocketChannel;
66 import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
67 import io.netty.handler.codec.LengthFieldPrepender;
68 import io.netty.handler.codec.string.StringDecoder;
69 import io.netty.handler.codec.string.StringEncoder;
70 import io.netty.util.CharsetUtil;
71
72 public class SocketServerInitializer extends ChannelInitializer {
73
74 @Override
75 protected void initChannel(SocketChannel socketChannel) throws Exception {
76
77 ChannelPipeline pipeline = socketChannel.pipeline();
78
79 pipeline.addLast("LengthFieldBasedFrameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
80 pipeline.addLast("LengthFieldPrepender",new LengthFieldPrepender(4));
81 pipeline.addLast("StringDecoder",new StringDecoder(CharsetUtil.UTF_8));
82 pipeline.addLast("StringEncoder",new StringEncoder(CharsetUtil.UTF_8));
83 pipeline.addLast("SocketServerHandler", new SocketServerHandler());
84 }
85 }

1 package com.bill.socketdemo;
2
3
4 import io.netty.bootstrap.Bootstrap;
5 import io.netty.channel.ChannelFuture;
6 import io.netty.channel.EventLoopGroup;
7 import io.netty.channel.nio.NioEventLoopGroup;
8 import io.netty.channel.socket.nio.NioSocketChannel;
9
10 public class SocketClient {
11
12 public static void main(String[] args) throws Exception {
13
14 // 这2个group都是死循环,阻塞式
15 EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
16
17 try {
18 Bootstrap bootstrap = new Bootstrap();
19 bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).
20 handler(new SocketClientInitializer());
21
22 ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync();
23 channelFuture.channel().closeFuture().sync();
24 } finally {
25 eventLoopGroup.shutdownGracefully();
26 }
27 }
28
29 }
30
31 package com.bill.socketdemo;
32
33 import io.netty.channel.ChannelHandlerContext;
34 import io.netty.channel.SimpleChannelInboundHandler;
35
36 import java.util.UUID;
37
38 public class SocketClientHandler extends SimpleChannelInboundHandler {
39
40 /**
41 * 发送内容给服务器端
42 */
43 @Override
44 protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
45 System.out.println(ctx.channel().remoteAddress());
46 System.out.println("client output:" + msg);
47 ctx.writeAndFlush("from client:" + UUID.randomUUID());
48 }
49
50 /**
51 * 该方法向服务器发数据,打破服务器-客户端一直等待对方发数据的僵局
52 */
53 @Override
54 public void channelActive(ChannelHandlerContext ctx) throws Exception {
55 ctx.writeAndFlush("from client: hello world");
56 }
57
58 /**
59 * 处理异常的方法,一旦出现异常,就会调用此方法
60 */
61 @Override
62 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
63 cause.printStackTrace();
64 ctx.close();
65 }
66 }
67
68 package com.bill.socketdemo;
69
70 import io.netty.channel.ChannelInitializer;
71 import io.netty.channel.ChannelPipeline;
72 import io.netty.channel.socket.SocketChannel;
73 import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
74 import io.netty.handler.codec.LengthFieldPrepender;
75 import io.netty.handler.codec.string.StringDecoder;
76 import io.netty.handler.codec.string.StringEncoder;
77 import io.netty.util.CharsetUtil;
78
79 public class SocketClientInitializer extends ChannelInitializer {
80
81 @Override
82 protected void initChannel(SocketChannel socketChannel) throws Exception {
83
84 ChannelPipeline pipeline = socketChannel.pipeline();
85
86 pipeline.addLast("LengthFieldBasedFrameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
87 pipeline.addLast("LengthFieldPrepender",new LengthFieldPrepender(4));
88 pipeline.addLast("StringDecoder",new StringDecoder(CharsetUtil.UTF_8));
89 pipeline.addLast("StringEncoder",new StringEncoder(CharsetUtil.UTF_8));
90 pipeline.addLast("SocketServerHandler", new SocketClientHandler());
91 }
92 }

执行结果

先运行服务器:

再运行客户端:

运行完客户端后服务器的情况

完整代码下载:

https://download.csdn.net/download/mweibiao/10551574

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器