Netty服务器部署在Android设备上,接收来自PC客户端的Java Socket客户端发送的JSON数据

Android 同时被 3 个专栏收录
669 篇文章 9 订阅
215 篇文章 0 订阅
3 篇文章 0 订阅

Netty服务器部署在Android设备上,接收来自PC客户端的Java Socket客户端发送的数据

 

一个简单的模型,在Android手机上部署一个Netty写的服务器,绑定端口9000,等待客户端连接,连接建立后,读取来自PC客户端的发送过来的字符串。

在Android手机上安装部署的Netty服务器:

package zhangphil.netttserver;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.util.logging.Level;
import java.util.logging.Logger;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.json.JsonObjectDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    new Server();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private class Server {
        private final int SERVER_PORT = 9000;

        public Server() throws Exception {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();

            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup).option(ChannelOption.SO_KEEPALIVE, true).channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128).handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel sc) throws Exception {
                            sc.pipeline().addLast(new JsonObjectDecoder());//JSon解码器。
                            sc.pipeline().addLast(new StringEncoder());// 发送字符串的编码器。
                            sc.pipeline().addLast(new StringDecoder());// 接收到字符串的解码器。
                            sc.pipeline().addLast(new MyChannelHandlerAdapter());
                        }
                    });

            // 绑定端口,开始接收进来的连接。
            ChannelFuture cf = b.bind(SERVER_PORT).sync();

            // 等待服务器关闭Socket。
            cf.channel().closeFuture().sync();
        }

        private class MyChannelHandlerAdapter extends ChannelHandlerAdapter {
            private final Logger logger = Logger.getLogger(MyChannelHandlerAdapter.class.getName());

            @Override
            public void channelActive(ChannelHandlerContext ctx) throws Exception {
                System.out.println("连接激活");
                ctx.writeAndFlush("hello,world!"); // 若没有StringEncoder,则发送不出去字符串。
                System.out.println("写入完成");
            }

            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                //ByteBuf buf = (ByteBuf) msg;
                logger.info(msg.toString());
                //System.out.println(buf.toString(CharsetUtil.UTF_8));
                //logger.info(msg.toString());
            }

            @Override
            public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
                logger.info("channelReadComplete");
            }

            @Override
            public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                logger.log(Level.WARNING, "发生错误,关闭链接。", cause);
                ctx.close();
            }
        }
    }
}

 

运行在PC电脑上的客户端,不停的发送字符串数据(转换成byte字节)。

import java.io.DataOutputStream;
import java.net.Socket;
import java.sql.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import com.google.gson.Gson;

public class Client {
	public Client() throws Exception {
		Socket socket = new Socket("localhost", 6000);
		System.out.println("连接建立:" + socket.toString());

		DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

		Date date = new Date(System.currentTimeMillis());
		DateFormat dateFormat = new SimpleDateFormat("MM-dd,HH:ss:SSS");

		Message message = new Message();

		Gson gson = new Gson();

		System.out.println("开始循环发一万次ping...");
		for (int i = 0; i < 10000; i++) {
			date.setTime(System.currentTimeMillis());
			message.time = dateFormat.format(date);
			String jsonString = gson.toJson(message);
			System.out.println(jsonString);

			dos.write(jsonString.getBytes("UTF-8"));
			dos.flush();

			Thread.sleep(1000);
		}
		System.out.println("循环一万次发ping结束");

		socket.close();
	}

	public static void main(String[] args) {
		try {
			new Client();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private class Message {
		public String data = "ping";
		public String time = "";
	}
}

 

两个程序运行前,需要手机连接电脑且打开调试模式,Android Studio发现手机。然后执行adb的tcp端口转发命令:

adb forward tcp:6000 tcp:9000

 

  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值