博主曾经对netty4的helloword很感兴趣,也曾单纯的写过一个小小的聊天室java代码,现在重新来看看,浏览了这位牛人的博客 点击去看看
我觉得受益匪浅,故拿来分享。
这次是在android上使用netty作为客户端,来与服务端相互通讯的小事例,纯粹的helloworld,效果就是在android程序中发送一个消息到服务端,然后服务端也回一个消息给客户端,很简单的demo,.大牛看了可不要吐槽啊!
1.demo结构
2.服务端代码:
Server.java
package org.jan.netty.demo; 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 MyHelloServer { private static final int PORT = 7878; public static void main(String[] args) { EventLoopGroup parentGroup = new NioEventLoopGroup(); EventLoopGroup childrenGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(parentGroup, childrenGroup); serverBootstrap.channel(NioServerSocketChannel.class); //添加工作线程 serverBootstrap.childHandler(new MyHelloServerInitializer()); // 服务器绑定端口监听 ChannelFuture cf = serverBootstrap.bind(PORT).sync(); // 监听服务器关闭监听 cf.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } finally { parentGroup.shutdownGracefully(); childrenGroup.shutdownGracefully(); } } }
MyHelloServerHandler.java
package org.jan.netty.demo; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import java.net.InetAddress; import java.nio.charset.Charset; public class MyHelloServerHanler extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { String recStr = new String(msg.getBytes(), Charset.forName("UTF-8")); //收到消息直接打印输出 System.out.println(ctx.channel().remoteAddress()+" say :"+recStr); //返回客户端 ctx.writeAndFlush("Received your message!\n"); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("RamoteAddress: "+ctx.channel().remoteAddress()+" active!"); // ctx.writeAndFlush("Welcome to " + InetAddress.getLocalHost().getHostName() + "'s service!\n"); ctx.writeAndFlush("我是服务端,我是服务端!\n"); super.channelActive(ctx); } }
3.android客户端代码:
/** * demo主界面:只有一个按钮发送消息 * @author jan */ public class ClientActivity extends Activity { private static final String TAG = "MainActivity"; private static Context context; public static int MSG_REC=0xabc; public static int PORT = 7878; public static final String HOST = "192.168.50.110"; private NioEventLoopGroup group; private Button sendButton; private Channel mChannel; private ChannelFuture cf; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what==MSG_REC){ Toast.makeText(context, msg.obj.toString(), 1000).show(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this; connected(); sendButton = (Button) findViewById(R.id.netty_send_button); sendButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { sendMessage(); } }); } // 连接到Socket服务端 private void connected() { new Thread() { @Override public void run() { group = new NioEventLoopGroup(); try { // Client服务启动器 3.x的ClientBootstrap // 改为Bootstrap,且构造函数变化很大,这里用无参构造。 Bootstrap bootstrap = new Bootstrap(); // 指定EventLoopGroup bootstrap.group(group); // 指定channel类型 bootstrap.channel(NioSocketChannel.class); // 指定Handler bootstrap.handler(new MyClientInitializer(context,mHandler)); bootstrap.option(ChannelOption.SO_KEEPALIVE, true); bootstrap.option(ChannelOption.TCP_NODELAY, true); bootstrap.option(ChannelOption.SO_TIMEOUT, 5000); // 连接到本地的7878端口的服务端 cf = bootstrap.connect(new InetSocketAddress( HOST, PORT)); mChannel = cf.sync().channel(); } catch (Exception e) { e.printStackTrace(); } } }.start(); } //发送数据 private void sendMessage() { mHandler.post(new Runnable() { @Override public void run() { try { Log.i(TAG, "mChannel.write sth & " + mChannel.isOpen()); mChannel.writeAndFlush("hello,this message is from client.\r\n"); mChannel.read(); } catch (Exception e) { e.printStackTrace(); } } }); } @Override protected void onDestroy() { super.onDestroy(); if (group != null) { group.shutdownGracefully(); } } }
public class MyClientInitializer extends ChannelInitializer<SocketChannel> { private Context context; private Handler handler; public MyClientInitializer(Context ctx,Handler handler){ this.context = ctx; this.handler = handler; } @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); /** * 这个地方的必须和服务端对应上。否则无法正常解码和编码 */ pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8)); //客户端的逻辑 pipeline.addLast("handler",new MyClientHandler(context,handler)); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("---channelRead--- msg="+msg); super.channelRead(ctx, msg); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { System.out.println("---channelReadComplete---"); super.channelReadComplete(ctx); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { Log.i("MyClientInitializer","---channelActive---"); super.channelActive(ctx); } }5.对应的数据处理类 ,没有什么新鲜性的东西哦。MyClientHandler.java
public class MyClientHandler extends SimpleChannelInboundHandler<String> { private Context ctx; private Handler handler; public MyClientHandler(Context context, Handler handler) { this.ctx = context; this.handler = handler; } @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { Log.d("MyHelloClientHandler", "channelRead0->msg="+msg); Message m = new Message(); m.what = ClientActivity.MSG_REC; m.obj = msg; handler.sendMessage(m); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client active"); super.channelActive(ctx); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client close "); super.channelInactive(ctx); } }
去下载demo