部落客曾經對netty4的helloword很感興趣,也曾單純的寫過一個小小的聊天室java代碼,現在重新來看看,浏覽了這位牛人的部落格 點選去看看
我覺得受益匪淺,故拿來分享。
這次是在android上使用netty作為用戶端,來與服務端互相通訊的小事例,純粹的helloworld,效果就是在android程式中發送一個消息到服務端,然後服務端也回一個消息給用戶端,很簡單的demo,.大牛看了可不要吐槽啊!
1.demo結構
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiIXZ05WZD9CX5RXa2Fmcn9CXwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVPNNDW1ZUbhZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DN5MjMygjM0EDMxIDM1EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
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();
}
}
}
4.用戶端中 bootstrap的初始化類MyClientInitializer.java
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