参考:

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


Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐