プロセスを開梱|実際の戦闘シリーズのAndroidアプリケーション開発における網状(4)---スティックパッケージ

バック第一章の始まりから見て示唆して記事を読みます

この一連の記事

まず、スティックパッケージは何でしょうか?

単純です:パッケージに被着体に複数のパケットを送信します。
例:サーバは、クライアントが本当に唯一のクライアントのために通常、(実際には2つのデータパケットのパッケージです)パッケージを受信した2つの連続したパケットが2つのパッケージを受け取る必要があります送信します。これは、あなたがアンパックプロセスを実行する必要があり、その場合には、クライアントスティックパッケージと呼ばれています。

第二に、スティックパッケージの一般的な処理手段

  • 固定長を使用します
  • 特殊文字のセグメンテーションを使用します($、\ nは...)
  • 他の

次のようにネッティーも、私たちにいくつかの処理デコーダスティックパッケージを提供しています。

  • DelimiterBasedFrameDecoder スティックのパッケージのための特別な文字に基づいて処理をアンパック
  • FixedLengthFrameDecoder アンパック処理は、固定棒パッケージの長さに基づいて行います
  • LengthFieldBasedFrameDecoder メッセージヘッダに基づいてプロセスをアンパックメッセージ長スティックパッケージを指定
  • LineBasedFrameDecoder 改行に基づく処理開梱スティックパッケージの場合(\ R \ nは、\ n)は、

私が使用開梱スティックパッケージを処理するために、以下の実施例により、第三に、DelimiterBasedFrameDecoderデコーダは、次に使用される$特殊な区切り文字として

まず、サーバーに3.1を追加DelimiterBasedFrameDecoder

/**
 * 启动tcp服务端
 */
public void startServer() {
    try {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    //分隔符
                    ByteBuf delimiter = Unpooled.copiedBuffer("$".getBytes());
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        //解决粘包
                        pipeline.addLast(new DelimiterBasedFrameDecoder(65535, delimiter));
                        //添加发送数据编码器
                        pipeline.addLast(new ServerEncoder());
                        //添加解码器,对收到的数据进行解码
                        pipeline.addLast(new ServerDecoder());
                        //添加数据处理
                        pipeline.addLast(new ServerHandler());
                    }
                });
        //服务器启动辅助类配置完成后,调用 bind 方法绑定监听端口,调用 sync 方法同步等待绑定操作完成
        b.bind(PORT).sync();
        handler.obtainMessage(0, "TCP 服务启动成功 PORT = " + PORT).sendToTarget();
        Log.d(TAG, "TCP 服务启动成功 PORT = " + PORT);
    } catch (Exception e) {
        e.printStackTrace();
    }

特別なセパレータを使用するので、3.2に追加され、その後、各データパケットを送信する必要性を処理するためのパッケージをスティック$シンボル、定義のみ必要Encoder、次のように追加します。

public class ServerEncoder extends MessageToByteEncoder<PkgDataBean> {

    private static final String TAG = "ServerEncoder";

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, PkgDataBean data, ByteBuf byteBuf) throws Exception {
        //根据数据包协议,生成byte数组
        byte[] bytes = {0x2A, data.getCmd(), data.getDataLength()};
        byte[] dataBytes = data.getData().getBytes();
        //分隔符
        byte[] delimiter = "$".getBytes();
        //将所有数据合并成一个byte数组
        byte[] all = ByteUtil.byteMergerAll(bytes, dataBytes, new byte[]{0x2A}, delimiter);
        //发送数据
        byteBuf.writeBytes(all);
    }
}

3.3我々は、コードの連続送信パケットを書きます

//获取与客户端的连接
List<ChannelHandlerContext> channels = ServerHandler.channels;
for (ChannelHandlerContext ctx : channels) {
    for (int i = 0; i < 3; i++) {
        PkgDataBean bean = new PkgDataBean();
        bean.setCmd((byte) 0x05);
        bean.setData("粘包的数据:" + i);
        bean.setDataLength((byte) bean.getData().getBytes().length);
        ctx.channel().writeAndFlush(bean);
    }
}
Log.d(TAG, "服务端发送了粘包数据");

サーバーが追加されましたので、第四に、DelimiterBasedFrameDecoderデコーダ、その後、クライアントは、同期を追加する必要があり、それ以外の場合は、異常なデータを解決することは不可能です

public void connect() {
    try {
        NioEventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap()
                // 指定channel类型
                .channel(NioSocketChannel.class)
                // 指定EventLoopGroup
                .group(group)
                // 指定Handler
                .handler(new ChannelInitializer<SocketChannel>() {
                    //分隔符
                    ByteBuf delimiter = Unpooled.copiedBuffer("$".getBytes());
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addLast(new IdleStateHandler(10, 0, 0));
                        //解决粘包
                        pipeline.addLast(new DelimiterBasedFrameDecoder(65535, delimiter));
                        //添加发送数据编码器
                        pipeline.addLast(new ClientEncoder());
                        //添加收到的数据解码器
                        pipeline.addLast(new ClientDecoder());
                        //添加数据处理器
                        pipeline.addLast(new ClientHandler(NettyClient.this));
                    }
                });
        // 连接到服务端
        ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress(IP, PORT));
        // 添加连接状态监听
        channelFuture.addListener(new ConnectListener(this));
        //获取连接通道
        channel = channelFuture.sync().channel();
        handler.obtainMessage(0, "连接成功").sendToTarget();
    } catch (Exception e) {
        handler.obtainMessage(0, "连接失败").sendToTarget();
        Log.e(TAG, "连接失败:" + e.getMessage());
        e.printStackTrace();
    }
}
  • 同様に、クライアントから送信されたデータは、パケットの終わり書き込みます$シンボルを。

第五に、今、プログラムの実行の効果を見て

  • サーバーは、3つの連続的なデータを送信します
    ここに画像を挿入説明
  • データは、クライアントが受信しました
    ここに画像を挿入説明

他のアンパックのために、あなたはそれについて話すでしょう、ここで全体のAndroidネッティーにおける基本的なアプリケーションに、彼らの実際の状況に応じて、適切な使用を選ぶことができるデコーダと、私はあなたがこの4つのブログでも実際の戦闘で使用することができます読んで信じています水にネッティーアヒル

ダウンロードデモの記事のこのシリーズ

一緒に交換QQグループへようこそ
ここに画像を挿入説明

公開された140元の記事 ウォンの賞賛546 ビュー540 000 +

おすすめ

転載: blog.csdn.net/a_zhon/article/details/101039462