当前位置:   article > 正文

使用Netty与Android构建简单C/S消息服务_netty server 怎么控制android

netty server 怎么控制android

使用Netty 构建简单C/S消息服务

Server

首先记得引入nettycompile 'io.netty:netty-all:4.1.13.Final'

  1. public class Server {
  2. private static final int PORT = 8999;
  3. public static void main(String[] args) {
  4. // NioEventLoopGroup is a multithreaded event loop that handles I/O operation.
  5. EventLoopGroup bossGroup = new NioEventLoopGroup(); // 用于处理客户端的连接请求
  6. EventLoopGroup workerGroup = new NioEventLoopGroup(); // 用于处理与各个客户端连接的IO操作
  7. // ServerBootstrap is a helper class that sets up a server.
  8. ServerBootstrap serverBootstrap = new ServerBootstrap();
  9. serverBootstrap.group(bossGroup, workerGroup)
  10. .channel(NioServerSocketChannel.class) // 使用Java Nio的Selector来处理新连接接入
  11. // ChannelInitializer是一个特殊的Handler用来帮助用户配置新Channel,一般用于在channelPipeline中新建channelHandler
  12. .childHandler(new ChannelInitializer<SocketChannel>() {
  13. @Override
  14. protected void initChannel(SocketChannel ch) throws Exception {
  15. ch.pipeline().addLast(new EchoServerHandler());
  16. }
  17. })
  18. .option(ChannelOption.SO_BACKLOG, 128) // 对应bossGroup
  19. .childOption(ChannelOption.SO_KEEPALIVE, true); // 对应workerGroup
  20. try {
  21. ChannelFuture channelFuture = serverBootstrap.bind(PORT).sync(); // 等待接入
  22. // Wait until the server socket is closed.
  23. // In this example, this does not happen, but you can do that to gracefully
  24. // shut down your server.
  25. channelFuture.channel().closeFuture().sync();
  26. } catch (InterruptedException e) {
  27. e.printStackTrace();
  28. } finally {
  29. workerGroup.shutdownGracefully();
  30. bossGroup.shutdownGracefully();
  31. }
  32. }
  33. }

ChannelInboundHandlerAdapter负责处理连接建立,收到消息。

  1. public class EchoServerHandler extends ChannelInboundHandlerAdapter {
  2. @Override
  3. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  4. super.channelActive(ctx);
  5. System.out.println("connected from:" + ctx.channel().remoteAddress());
  6. }
  7. @Override
  8. public void channelInactive(ChannelHandlerContext ctx) throws Exception {
  9. super.channelInactive(ctx);
  10. }
  11. @Override
  12. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  13. ByteBuf byt = (ByteBuf) msg;
  14. byte[] bytesSrc = new byte[byt.readableBytes()];
  15. byt.readBytes(bytesSrc);
  16. String data = new String(bytesSrc);
  17. System.out.println("received:" + data + " from:" + ctx.channel().remoteAddress());
  18. String response = "response: " + data;
  19. ByteBuf responseBuf = ctx.alloc().buffer(response.length());
  20. responseBuf.writeBytes(response.getBytes());
  21. ctx.channel().writeAndFlush(responseBuf);
  22. byt.release(); // 释放资源
  23. }
  24. @Override
  25. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  26. cause.printStackTrace();
  27. ctx.close();
  28. }
  29. }

Client

  1. public class MainActivity extends AppCompatActivity {
  2. private EditText mIpEt;
  3. private EditText mPortEt;
  4. private Button mConnBtn;
  5. private TextView mScreenTv;
  6. private EditText mInputEt;
  7. private Button mSendBtn;
  8. private SocketThread mSocketThread;
  9. private static Handler mMainHandler;
  10. public static final int MSG_CONNECT = 0x001;
  11. public static final int MSG_RECEIVE = 0x002;
  12. public static final int MSG_SEND = 0x003;
  13. public static final String DATA_RECEIVE = "data_receive";
  14. public static final String DATA_SEND = "data_send";
  15. @Override
  16. protected void onCreate(@Nullable Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.activity_main);
  19. mIpEt = findViewById(R.id.main_ip_et);
  20. mPortEt = findViewById(R.id.main_port_et);
  21. mConnBtn = findViewById(R.id.main_connect_btn);
  22. mScreenTv = findViewById(R.id.main_screen_tv);
  23. mInputEt = findViewById(R.id.main_input_et);
  24. mSendBtn = findViewById(R.id.main_send_btn);
  25. // defalut value. Change it to your own server ip
  26. mIpEt.setText("172.16.62.65");
  27. mPortEt.setText("8999");
  28. mConnBtn.setOnClickListener(new View.OnClickListener() {
  29. @Override
  30. public void onClick(View v) {
  31. String ip = mIpEt.getText().toString();
  32. String port = mPortEt.getText().toString();
  33. if (TextUtils.isEmpty(ip) || TextUtils.isEmpty(port)) {
  34. Toast.makeText(MainActivity.this, "ip or port is null", Toast.LENGTH_SHORT).show();
  35. } else {
  36. connectToServer(ip, Integer.valueOf(port));
  37. }
  38. }
  39. });
  40. mSendBtn.setOnClickListener(new View.OnClickListener() {
  41. @Override
  42. public void onClick(View v) {
  43. String data = mInputEt.getText().toString();
  44. if (!TextUtils.isEmpty(data)) {
  45. mSocketThread.sendMessage(data);
  46. }
  47. }
  48. });
  49. // TODO handler may cause memory leaks
  50. mMainHandler = new Handler() {
  51. @Override
  52. public void handleMessage(Message msg) {
  53. switch (msg.what) {
  54. case MSG_CONNECT:
  55. Toast.makeText(MainActivity.this, "Connect to Server Success", Toast.LENGTH_SHORT).show();
  56. mConnBtn.setText("Connected");
  57. mConnBtn.setEnabled(false);
  58. break;
  59. case MSG_RECEIVE:
  60. Bundle data = msg.getData();
  61. String dataStr = data.getString(DATA_RECEIVE);
  62. CharSequence originData = mScreenTv.getText();
  63. String result = originData + "\n" + dataStr;
  64. mScreenTv.setText(result);
  65. break;
  66. }
  67. }
  68. };
  69. }
  70. private void connectToServer(String ip, int port) {
  71. mSocketThread = new SocketThread(ip, port);
  72. mSocketThread.start();
  73. }
  74. private static class SocketThread extends Thread {
  75. private Channel mChannel;
  76. private String mIp;
  77. private int mPort;
  78. private SendThread mSendThread;
  79. public SocketThread(String ip, int port) {
  80. this.mIp = ip;
  81. this.mPort = port;
  82. }
  83. @Override
  84. public void run() {
  85. EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
  86. Bootstrap clientBootStrap = new Bootstrap();
  87. clientBootStrap.group(eventLoopGroup)
  88. .channel(NioSocketChannel.class)
  89. .option(ChannelOption.TCP_NODELAY, true)
  90. .handler(new ChannelInitializer<SocketChannel>() {
  91. @Override
  92. protected void initChannel(SocketChannel ch) throws Exception {
  93. ch.pipeline().addLast(new EchoClientHandler(mMainHandler));
  94. }
  95. });
  96. try {
  97. // Start the client.
  98. ChannelFuture future = clientBootStrap.connect(mIp, mPort).sync();
  99. mChannel = future.channel();
  100. mSendThread = new SendThread(mChannel);
  101. mSendThread.start();
  102. // Wait until the connection is closed.
  103. mChannel.closeFuture().sync();
  104. } catch (InterruptedException e) {
  105. e.printStackTrace();
  106. } finally {
  107. eventLoopGroup.shutdownGracefully();
  108. }
  109. }
  110. public void sendMessage(String data) {
  111. Handler socketHandler = mSendThread.getSocketHandler();
  112. Message message = socketHandler.obtainMessage();
  113. message.what = MSG_SEND;
  114. Bundle bundle = new Bundle();
  115. bundle.putString(DATA_SEND, data);
  116. message.setData(bundle);
  117. socketHandler.sendMessage(message);
  118. }
  119. }
  120. private static class SendThread extends Thread {
  121. private Handler mSocketHandler;
  122. private Channel mChannel;
  123. public SendThread(Channel channel) {
  124. mChannel = channel;
  125. }
  126. @Override
  127. public void run() {
  128. // init child thread handler
  129. if (mSocketHandler == null) {
  130. Looper.prepare();
  131. mSocketHandler = new Handler(Looper.myLooper()) {
  132. @Override
  133. public void handleMessage(Message msg) {
  134. switch (msg.what) {
  135. case MSG_SEND:
  136. String data = msg.getData().getString(DATA_SEND);
  137. ByteBuf byteBuf = Unpooled.buffer(data.length()); //使用非池化Buffer去申请内存,这里待优化
  138. byteBuf.writeBytes(data.getBytes());
  139. mChannel.writeAndFlush(byteBuf);
  140. break;
  141. }
  142. }
  143. };
  144. }
  145. Looper.loop();
  146. }
  147. public Handler getSocketHandler() {
  148. return mSocketHandler;
  149. }
  150. }
  151. }

ChannelInboundHandlerAdapter实现代码,用于处理连接建立、收到消息。

  1. public class EchoClientHandler extends ChannelInboundHandlerAdapter {
  2. private Handler mMainHandler;
  3. public EchoClientHandler(Handler handler) {
  4. mMainHandler = handler;
  5. }
  6. @Override
  7. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  8. super.channelActive(ctx);
  9. mMainHandler.sendEmptyMessage(MainActivity.MSG_CONNECT);
  10. }
  11. @Override
  12. public void channelInactive(ChannelHandlerContext ctx) throws Exception {
  13. super.channelInactive(ctx);
  14. }
  15. @Override
  16. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  17. ByteBuf byt = (ByteBuf) msg;
  18. byte[] bytesSrc = new byte[byt.readableBytes()];
  19. byt.readBytes(bytesSrc);
  20. String data = new String(bytesSrc);
  21. Message message = mMainHandler.obtainMessage();
  22. message.what = MainActivity.MSG_RECEIVE;
  23. Bundle extra = new Bundle();
  24. extra.putString(MainActivity.DATA_RECEIVE, data);
  25. message.setData(extra);
  26. mMainHandler.sendMessage(message);
  27. byt.release(); // 释放资源
  28. }
  29. @Override
  30. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  31. cause.printStackTrace();
  32. ctx.close();
  33. }
  34. }

Layout

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical"
  6. android:layout_margin="15dp">
  7. <EditText
  8. android:id="@+id/main_ip_et"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:hint="ip address"/>
  12. <EditText
  13. android:id="@+id/main_port_et"
  14. android:layout_width="match_parent"
  15. android:layout_height="wrap_content"
  16. android:hint="port"
  17. android:inputType="number"/>
  18. <Button
  19. android:id="@+id/main_connect_btn"
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:layout_gravity="center"
  23. android:text="Connect"/>
  24. <EditText
  25. android:id="@+id/main_input_et"
  26. android:layout_width="match_parent"
  27. android:layout_height="wrap_content"
  28. android:hint="message to server"/>
  29. <Button
  30. android:id="@+id/main_send_btn"
  31. android:layout_width="wrap_content"
  32. android:layout_height="wrap_content"
  33. android:layout_gravity="center"
  34. android:text="Send"/>
  35. <ScrollView
  36. android:layout_width="match_parent"
  37. android:layout_height="match_parent"
  38. android:layout_marginTop="10dp">
  39. <TextView
  40. android:id="@+id/main_screen_tv"
  41. android:layout_width="match_parent"
  42. android:layout_height="wrap_content"
  43. android:text="received message will be shown here"/>
  44. </ScrollView>
  45. </LinearLayout>

Run


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/160739
推荐阅读
相关标签
  

闽ICP备14008679号