博主曾经对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 {
@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 {
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 {
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