参考:
Netty 实现聊天功能 - waylau的个人页面 - 开源中国社区 http://my.oschina.net/waylau/blog/380957
在此基础上制作Android版本
服务器三个文件
SubReqServer.java
SimpleChatServerInitializer.java
SimpleChatServerHandler.java
SubReqServer.java
package com.test.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; public class SubReqServer { public void run(int nPort) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try{ ServerBootstrap b = new ServerBootstrap(); // (2) b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // (3) .childHandler(new SimpleChatServerInitializer()) //(4) .option(ChannelOption.SO_BACKLOG, 128) // (5) .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) System.out.println("服务器已启动,等待客户端连接"); // 绑定端口,开始接收进来的连接 ChannelFuture f = b.bind(nPort).sync(); // (7) // 等待服务器 socket 关闭 。 // 在这个例子中,这不会发生,但你可以优雅地关闭你的服务器。 f.channel().closeFuture().sync(); }finally { System.out.println("---------------Shut down"); bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args){ int nPort = 9999; nPort = Integer.valueOf(nPort); System.out.println("---------------Main start"); try { new SubReqServer().run(nPort); } catch (Exception e) { System.out.println("---------------Main Error"); e.printStackTrace(); } } }
SimpleChatServerInitializer.java
package com.test.netty; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class SimpleChatServerInitializer extends ChannelInitializer<SocketChannel> { @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); pipeline.addLast("handler", new SimpleChatServerHandler()); System.out.println("SimpleChatClient:"+ch.remoteAddress() +"连接上"); } }
SimpleChatServerHandler.java
package com.test.netty; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; import io.netty.util.concurrent.GlobalEventExecutor; public class SimpleChatServerHandler extends SimpleChannelInboundHandler<String> { // (1) /** * A thread-safe Set Using ChannelGroup, you can categorize Channels into a meaningful group. * A closed Channel is automatically removed from the collection, */ public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { // (2) Channel incoming = ctx.channel(); System.out.println("---------------handlerAdded"); // Broadcast a message to multiple Channels channels.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 加入\n"); channels.add(ctx.channel()); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { // (3) Channel incoming = ctx.channel(); System.out.println("---------------handlerRemoved"); // Broadcast a message to multiple Channels channels.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 离开\n"); // A closed Channel is automatically removed from ChannelGroup, // so there is no need to do "channels.remove(ctx.channel());" } @Override protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception { // (4) System.out.println("---------------channelRead0 have received : " + s + " "); Channel incoming = ctx.channel(); for (Channel channel : channels) { if (channel != incoming){ channel.writeAndFlush("[" + incoming.remoteAddress() + "]" + "Hello " + "\n"); } else { channel.writeAndFlush("[you]" + s + "\n"); } } } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // (5) Channel incoming = ctx.channel(); System.out.println("SimpleChatClient:---"+incoming.remoteAddress()+"---在线"); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { // (6) Channel incoming = ctx.channel(); System.out.println("SimpleChatClient:---"+incoming.remoteAddress()+"---掉线"); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { Channel incoming = ctx.channel(); System.out.println("SimpleChatClient:---"+incoming.remoteAddress()+"---异常"); // 当出现异常就关闭连接 cause.printStackTrace(); ctx.close(); } }
客户端四个文件
MainActivity.java
TcpClient.java
SimpleChatClientInitializer.java
SimpleChatClientHandler.java
MainActivity.java
package com.example.videonetty; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.Button; public class MainActivity extends Activity { Button btnSend; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSend = (Button)findViewById(R.id.btnSend); //Netty 线程 TcpClient client = new TcpClient(); client.start(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
TcpClient.java
package com.example.videonetty; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; public class TcpClient extends Thread { public static String HOST = "168.168.1.121"; public static int PORT = 9999; public void run() { super.run(); EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap() .group(group) .channel(NioSocketChannel.class) .handler(new SimpleChatClientInitializer()); Channel channel = bootstrap.connect(HOST, PORT).sync().channel(); while(true){ channel.writeAndFlush("this msg test come from client" + "\r\n"); Thread.currentThread(); Thread.sleep(1000); } } catch (Exception e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } }
SimpleChatClientInitializer.java
package com.example.videonetty; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class SimpleChatClientInitializer extends ChannelInitializer<SocketChannel>{ public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); pipeline.addLast("handler", new SimpleChatClientHandler()); } }
SimpleChatClientHandler.java
package com.example.videonetty; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; public class SimpleChatClientHandler extends SimpleChannelInboundHandler<String> { protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception { System.out.println("---------------channelRead0 have received : " + s + " "); } }
效果:
服务器:
---------------Main start
服务器已启动,等待客户端连接
---------------handlerAdded
SimpleChatClient:/172.16.25.2:41291连接上
SimpleChatClient:---/172.16.25.2:41291---在线
---------------channelRead0 have received : this msg test come from client
---------------channelRead0 have received : this msg test come from client
---------------channelRead0 have received : this msg test come from client
---------------channelRead0 have received : this msg test come from client
---------------channelRead0 have received : this msg test come from client
客户端:
04-07 06:34:17.029: I/System.out(14664): ---------------channelRead0 have received : [you]this msg test come from client
........
源码下载: Eclipse + Netty 4.0.035
http://download.csdn.net/detail/yulinxx/9483752