服务器实时向Android推送消息的几种实现方式

近期项目中需要实现服务器端实时向客户端推送消息,客户端接收消息做完处理以后再返回服务端,也就是要实现服务器端和客户端实时的双向通信。

使用有线的双向推送:

基于USB HID通信协议:
需要在PC端和安卓端商定好传输数据格式:
在PC端运行发送和接受文件的驱动,实现可通过网页调用PC端的驱动;
在Android端需要打开USB 和HID设备,打开USB和HID,打开接收和发送的接口,关闭通道。

  1. 打开设备
public boolean open() {
        File fd = new File("/dev/hidg0");
        try {
            outHid = new FileOutputStream(fd);
            inHid = new FileInputStream(fd);
            return true;
        } catch (FileNotFoundException e2) {
            Log.i("lbl", "HidOpenFill");
            e2.printStackTrace();
            return false;
        }
    }
  1. 发送数据
public void sendOneFrame(byte sendBuf[]) {
       try {
           byte[] send = new byte[1024];
           System.arraycopy(sendBuf, 0, send, 0, sendBuf.length);
           this.outHid.write(send);
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
  1. 读取报文
  public int readReport(byte RxBuf[]) {
       int ret = -1;
       if (null != this.inHid) {
           try {
               for (int i = 0; i < 1024; i++) {
                   RxBuf[i] = 0;
               }
               ret = this.inHid.read(RxBuf, 0, 1024);
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
       return ret;
   }

4.关闭文件流

 public boolean close() {
        try {
            if (outHid != null)
                outHid.close();
            if (inHid != null)
                inHid.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

基于无线网络的双向推送:

同一个网段中可以使用
Socket:
接受文件的一方作为socketServer,接受socketClient发送的文件。
接受到文件后,解析出socketClient的IP地址,将处理完成的文件通过HTTP的形式传输到PC端。

try {
			Socket socket = new Socket("192.168.10.147",11900);
			
			OutputStream os = (OutputStream) socket.getOutputStream();//字节输出流
			PrintWriter pw =new PrintWriter(os);//将输出流包装成打印流
			pw.write("用户名:admin;密码:admin");
			pw.flush();
			socket.shutdownOutput();
			pw.close();
			os.close();
			socket.close();
			
			System.out.println("send ok");
			 
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
ServerSocket serverSocket = null;
		try {
			int port = 11900;
			InetSocketAddress address;
			address = new InetSocketAddress(port);
			serverSocket = new ServerSocket();
			serverSocket.setReuseAddress(true);
			serverSocket.bind(address);

		} catch (Exception e) {
			e.printStackTrace();
		}
		while (true) {
			BufferedReader in = null;
			Socket s = null;
			try {
				s = serverSocket.accept();
				InetAddress clienAdr = s.getInetAddress();
				System.out.println(clienAdr.getHostAddress());
				in = new BufferedReader(new InputStreamReader(
						s.getInputStream()));
				StringBuffer result = new StringBuffer();
				String line;
				while ((line = in.readLine()) != null) {
					result.append(line);
				}
				s.shutdownInput();
				in.close();
				in = null;
				s.close();
				s = null;
				System.out.println(result.toString());
			} catch (Exception e) {

				if (in != null) {
					try {
						in.close();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					in = null;
				}
				if (s != null) {
					try {
						s.close();
					} catch (IOException e1) {
						e1.printStackTrace();
					}
					s = null;
				}
			}

		}

Netty
可以设置通信协议和通信通道,可实现根据不同的协议实现数据的传输;

public class NettyClient {
    private String host;
    private int port;
    private String msg;
    private static final int HEARTBEAT_INTERVAL = 5; // 心跳间隔时间,单位:秒

    public NettyClient(String host, int port,String msg) {
        this.host = host;
        this.port = port;
        this.msg = msg;
    }

    public void run() throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .remoteAddress(host, port)
                    .handler(new ChannelInitializer<NioSocketChannel>() {
                        @Override
                        public void initChannel(NioSocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new StringEncoder());
                            pipeline.addLast(new StringDecoder());
                            pipeline.addLast(new IdleStateHandler(0, 0, HEARTBEAT_INTERVAL, TimeUnit.SECONDS)); // 添加心跳处理器
                            ch.pipeline().addLast(new NettyClientHandler());
                        }
                    });

            ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
            channelFuture.channel().writeAndFlush(msg).sync();
        } finally {
            group.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        new NettyClient("192.168.10.160", 11900,"hello,server").run();
    }
}

public class NettyClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(Unpooled.copiedBuffer("你好,服务器!",CharsetUtil.UTF_8));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf= (ByteBuf) msg;
        System.out.println("接收到服务端响应:"+byteBuf.toString(CharsetUtil.UTF_8));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    // 用来触发特殊事件
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception{
        IdleStateEvent event = (IdleStateEvent) evt;
        // 触发了读空闲事件
        if (event.state() == IdleState.READER_IDLE) {
            ctx.channel().close();
        }
    }
}

public class NettyServer implements Runnable {

    private int port;
    private SendMessage sendMessage;
    private Handler handler;

    public NettyServer(int port,Handler handler, SendMessage sendMessage) {
        this.port = port;
        this.sendMessage = sendMessage;
        this.handler = handler;
    }

    public NettyServer() {
    }

    public void run() {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.childOption(ChannelOption.SO_KEEPALIVE, true);
            b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
//                        .childHandler(new MyChannelInitializer(sendMessage,handler));
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    public void initChannel(NioSocketChannel channel){
                        channel.pipeline().addLast(new StringDecoder());
                        //添加心跳检查包
                        channel.pipeline().addLast(new IdleStateHandler(5,0,0, TimeUnit.SECONDS));
                        channel.pipeline().addLast(new MyServerHandler(handler,sendMessage));
                    }
                });
            b.bind(port).sync().channel().closeFuture().sync();
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}

public class MyServerHandler extends ChannelInboundHandlerAdapter {
    private SendMessage sendMessage;
    private Handler handler;

    public MyServerHandler(Handler handler,SendMessage sendMessage) {
        this.sendMessage = sendMessage;
        this.handler = handler;
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception{
        IdleStateEvent event = (IdleStateEvent) evt;
        // 触发了读空闲事件
        if (event.state() == IdleState.READER_IDLE) {
            ctx.channel().close();
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        System.out.println(msg);
        String res = handMsg(msg);
        ctx.writeAndFlush(res);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //发送消息给客户端
        ctx.writeAndFlush(Unpooled.copiedBuffer("服务端已收到消息,并给你发送一个问号?", CharsetUtil.UTF_8));
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }

    private String handMsg(Object msg){
        String revdata = msg.toString();
        String outbytes = "";
        if (sendMessage != null ) {
            outbytes = sendMessage.SendByteData(handler,revdata);
        }
        return outbytes;
    }


}

服务器和APP处于不同的网段,可以使用MPush实现实时的通讯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值