Netty处理TCP连接的session

来源:互联网 发布:下载最快的软件 编辑:程序博客网 时间:2024/06/07 04:05

Netty处理TCP连接的session

在同步阻塞的网络编程中,代码都是按照TCP操作顺序编写的,即创建连接、多次读写、关闭连接,这样很容易判断这一系列操作是否是同一个连接。而在事件驱动的异步网络编程框架中,IO操作都会触发一个事件调用相应的事件函数,例如接收到客户端的新数据,会调用messageReceived(MINA)、channelRead(Netty)、dataReceived(Twisted),同一个TCP连接的多次请求和多个客户端请求都是一样的。
那么如何判断多次请求到底是不是同一个TCP连接,如何保存连接相关的信息?针对这个问题,Netty都提供了相应的解决方案。

首先创建一个tcp服务器:

package session;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelHandler.Sharable;import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.LineBasedFrameDecoder;import io.netty.handler.codec.http.multipart.Attribute;import io.netty.handler.codec.string.StringDecoder;import io.netty.util.AttributeKey;import io.netty.util.CharsetUtil;public class TcpServer {public static void main(String[] args) throws InterruptedException {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {private TcpServerHandler tcpServerHandler = new TcpServerHandler();@Overridepublic void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new LineBasedFrameDecoder(80));pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));pipeline.addLast(tcpServerHandler); // 多个连接使用同一个ChannelHandler实例}});ChannelFuture f = b.bind(6699).sync();System.out.println("TcpServer.main()");f.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}}@Sharable // 多个连接使用同一个ChannelHandler,要加上@Sharable注解class TcpServerHandler extends ChannelInboundHandlerAdapter {private AttributeKey<Integer> attributeKey = AttributeKey.valueOf("counter");@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {io.netty.util.Attribute<Integer> attribute = ctx.attr(attributeKey);int counter = 1;if(attribute.get() == null) {attribute.set(1);} else {counter = attribute.get();counter++;attribute.set(counter);}String line = (String) msg;System.out.println("第" + counter + "次请求:" + line);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}}

客户端:

package session;import java.io.IOException;import java.io.OutputStream;import java.net.Socket;public class TcpClient {public static void main(String[] args) throws IOException, InterruptedException {// 3次TCP连接,每个连接发送2个请求数据for(int i = 0; i < 3; i++) {Socket socket = null;OutputStream out = null;try {socket = new Socket("localhost", 6699);out = socket.getOutputStream();// 第一次请求服务器String lines1 = "Hello\r\n";byte[] outputBytes1 = lines1.getBytes("UTF-8");out.write(outputBytes1);out.flush();// 第二次请求服务器String lines2 = "World\r\n";byte[] outputBytes2 = lines2.getBytes("UTF-8");out.write(outputBytes2);out.flush();} finally {// 关闭连接out.close();socket.close();}Thread.sleep(1000);}}}
原创粉丝点击