国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Springboot使用Netty連接Tcp接口(c語言二進制字節(jié)碼轉(zhuǎn)java字符串)

這篇具有很好參考價值的文章主要介紹了Springboot使用Netty連接Tcp接口(c語言二進制字節(jié)碼轉(zhuǎn)java字符串)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

   **使用java編碼的springboot項目在調(diào)用C語言等其他語言編寫的Tcp接口時,使用netty框架可以實現(xiàn)數(shù)據(jù)雙向持續(xù)交互處理。
   注:在交互過程中,c語言生成的二進制字節(jié)碼轉(zhuǎn)java字符串時往往出現(xiàn)亂碼,請看后面處理方式(netty處理類中的代碼)。**

一、引入netty的jar包

io.netty
netty-all

二、使用netty框架
1、創(chuàng)建客戶端
package com.iflytek.digtal.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

/**

  • netty客戶端
    */
    public class NettyClient {

    /**

    • 連接tcp服務(wù)端初始化

    • @throws InterruptedException
      */
      public static void init() throws InterruptedException {
      //客戶端需要一個事件循環(huán)組
      NioEventLoopGroup group = new NioEventLoopGroup();

      try {
      //創(chuàng)建客戶端啟動對象
      //注意客戶端使用的不是SocketBootstrap而是Bootstrap
      Bootstrap bootstrap = new Bootstrap();

       // 設(shè)置相關(guān)參數(shù)
       bootstrap.group(group) //設(shè)置線程組
               .channel(NioSocketChannel.class)// 使用NioSocketChannel作為客戶端的通道實現(xiàn)
               .handler(new ChannelInitializer<SocketChannel>() {
                   @Override
                   protected void initChannel(SocketChannel ch) throws Exception {
                       ch.pipeline().addLast(new NettyClientHandler());
                   }
               });
      
       System.out.println("netty client start..");
       ChannelFuture cf = bootstrap.connect("127.0.0.1", 6000).sync();
      
       cf.channel().closeFuture().sync();
      

      }finally {
      group.shutdownGracefully();
      }
      }

    public static void main(String[] args) throws InterruptedException {
    //客戶端需要一個事件循環(huán)組
    NioEventLoopGroup group = new NioEventLoopGroup();

     try {
         //創(chuàng)建客戶端啟動對象
         //注意客戶端使用的不是SocketBootstrap而是Bootstrap
         Bootstrap bootstrap = new Bootstrap();
    
         // 設(shè)置相關(guān)參數(shù)
         bootstrap.group(group) //設(shè)置線程組
                 .channel(NioSocketChannel.class)// 使用NioSocketChannel作為客戶端的通道實現(xiàn)
                 .handler(new ChannelInitializer<SocketChannel>() {
                     @Override
                     protected void initChannel(SocketChannel ch) throws Exception {
                         ch.pipeline().addLast(new NettyClientHandler());
                     }
                 });
    
         System.out.println("netty client start..");
         ChannelFuture cf = bootstrap.connect("127.0.0.1", 6000).sync();
    
         cf.channel().closeFuture().sync();
     }finally {
         group.shutdownGracefully();
     }
    

    }

}
2、創(chuàng)建服務(wù)端
package com.iflytek.digtal.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class NettyServer {

public static void main(String[] args) throws InterruptedException {
    //創(chuàng)建兩個線程組bossGroup和workerGroup,含有的子線程NioEventLoop的個數(shù)默認(rèn)是CPU的兩倍
    //bossGroup只是處理連接請求,真正的和客戶端業(yè)務(wù)處理,會交給workerGroup完成
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup(1);

    try {
        //創(chuàng)建服務(wù)器端的啟動對象
        ServerBootstrap bootstrap = new ServerBootstrap();
        //使用鏈?zhǔn)骄幊虂砼渲脜?shù)
        bootstrap.group(bossGroup, workerGroup)//設(shè)置兩個線程組
                .channel(NioServerSocketChannel.class)//使用NioServerSocketChannel作為服務(wù)器的通道實現(xiàn)
                //初始化服務(wù)器連接隊列大小,服務(wù)端處理客戶端連接請求是順序處理的,所以同一時間只能處理一個客戶端連接
                //多個客戶端同時來的時候,服務(wù)端將不能處理的客戶端連接請求放在隊列中等待處理
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel channel) throws Exception {
                        //對workerGroup的SocketChannel設(shè)置處理器
                        channel.pipeline().addLast(new NettyServerHandler());
                    }
                });

        System.out.println("netty server start..");

        //綁定一個端口并且同步生成一個ChannelFuture異步對象,通過isDone()等方法可以判斷異步事件的執(zhí)行情況
        //啟動服務(wù)器(并綁定的端口),bind是異步操作,sync方法是等待異步操作執(zhí)行完畢
        ChannelFuture cf = bootstrap.bind(9000).sync();

        //給cf注冊監(jiān)聽器,監(jiān)聽我們關(guān)心的事件
        cf.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (cf.isSuccess()) {
                    System.out.println("監(jiān)聽端口9000成功");
                } else {
                    System.out.println("監(jiān)聽端口9000失敗");
                }
            }
        });
        //等待服務(wù)端監(jiān)聽端口關(guān)閉,closeFuture是異步操作
        //通過sync方法同步等待通道關(guān)閉處理完畢,這里會阻塞等待通道關(guān)閉完成,內(nèi)部調(diào)用的是Object的wait()方法
        cf.channel().closeFuture().sync();

    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }

}

}
3、編寫處理類
package com.iflytek.digtal.netty2;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;

/**

  • 處理類
    */
    @Slf4j
    public class NettyClientHandler2 extends ChannelInboundHandlerAdapter {

    /**

    • 客戶端連接標(biāo)識
    • @param ctx
    • @throws Exception
      */
      @Override
      public void channelActive(ChannelHandlerContext ctx) throws Exception {
      ByteBuf buf = Unpooled.copiedBuffer(“HelloServer”.getBytes(Charset.forName(“GBK”)));
      ctx.writeAndFlush(buf);
      }

    //當(dāng)通道建立后有事件時會觸發(fā),即服務(wù)端發(fā)送數(shù)據(jù)給客戶端
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

     ByteBuf buf = (ByteBuf) msg;
     log.info("哈哈哈:{}",msg);
     // 復(fù)制內(nèi)容到字節(jié)數(shù)組bytes
     byte[] bytes = new byte[buf.readableBytes()];
     buf.readBytes(bytes);
     log.info("收到的數(shù)據(jù)為:{}", bytes);
    
     int[] lengthArr = {4,4,4,4,4,4,56,24,56,24,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,56,32,8};
     String[] strArr = {"int","int","int","int","int","int","char","char","char","char",
             "float","float","int","int","float","float","float","float","int","int","int","int",
             "int","int","int","int","char","char","systime"};
    
     String[] strs = new String[29];
     int offset = 0;
     for(int i =0;i<29;i++){
         byte[] bytes1 = new byte[lengthArr[i]];
         System.arraycopy(bytes, offset, bytes1, 0, lengthArr[i]);
         offset = offset + lengthArr[i];
         if("int".equals(strArr[i])){
             strs[i] = String.valueOf(bytesToInt(bytes1,0));
         }else if("char".equals(strArr[i])){
             strs[i] = bytesToChar(bytes1);
         }else if("float".equals(strArr[i])){
             strs[i] = String.valueOf(byteToFloat(bytes1,0));
         }else if("systime".equals(strArr[i])){
             strs[i] = bytesToChar(bytes1);
         }
     }
     System.out.println("二進制數(shù)據(jù)轉(zhuǎn)化后的結(jié)果:"+ Arrays.toString(strs));
    
     // 前六個int數(shù)值
     String[] str = new String[6];
     for(int i =0,j=0;j<24;i++){
         str[i] = String.valueOf(bytesToInt(bytes,j));
         j = j+4;
     }
     System.out.println("str:"+ Arrays.toString(str));
    
     //第七個試驗名稱
     byte[] bytes1 = new byte[56];
     System.arraycopy(bytes, 24, bytes1, 0, 56);
    

// for(int i=0;i<56;i++){
// bytes1[i] = bytes[20+i];
// }
log.info(“試驗名稱字節(jié)數(shù)組為:{}”, bytes1);
String str1 = bytesToChar(bytes1);
System.out.println(“試驗名稱str1:”+str1);

    //第八個通道名稱
    byte[] bytes2 = new byte[24];
    System.arraycopy(bytes, 80, bytes2, 0, 24);

// for(int i=0;i<56;i++){
// bytes1[i] = bytes[20+i];
// }
log.info(“通道名稱字節(jié)數(shù)組為:{}”, bytes2);
String str2 = bytesToChar(bytes2);
System.out.println(“通道名稱str2:”+str2);

    //第九個采集名稱
    byte[] bytes3 = new byte[56];
    System.arraycopy(bytes, 104, bytes3, 0, 56);

// for(int i=0;i<56;i++){
// bytes1[i] = bytes[20+i];
// }
log.info(“采集名稱字節(jié)數(shù)組為:{}”, bytes3);
String str3 = bytesToChar(bytes3);
System.out.println(“采集名稱str3:”+str3);

    System.out.println("服務(wù)端地址是:" + ctx.channel().remoteAddress());

}

public  int combine(byte b[])
{
    int t1=(b[3]&0xff)<<24;
    int t2=(b[2]&0xff)<<16;
    int t3=(b[1]&0xff)<<8;
    int t4=b[0]&0xff;
    //System.out.println(b[1]&0xff);//輸出的是一個整形數(shù)據(jù)
    //在java中,設(shè)計int和比int位數(shù)來的小的類型b,如byte,char等,都是先把小類型擴展成int再來運算,
    //return( t1<<24)+(t2<<16)+(t3<<8)+t4;//必須加括號
    return t1+t2+t3+t4;
}

private char[] getChars (byte[] bytes) {

    Charset cs = Charset.forName ("GBK");

    ByteBuffer bb = ByteBuffer.allocate (bytes.length);

    bb.put (bytes);

    bb.flip ();

    CharBuffer cb = cs.decode (bb);

    return cb.array();

}

/**
 * byte轉(zhuǎn)int
 * @Title: bytesToInt
 *
 * @param: @param src 源數(shù)組
 * @param: @param offset 起始偏移量
 * @return: int
 */
public int bytesToInt(byte[] src, int offset) {
    int value;
    value = src[offset] & 0xFF;
    value |= ((long) (src[offset + 1] & 0xFF) << 8);
    value |= ((long) (src[offset + 2] & 0xFF) << 16);
    value |= ((long) (src[offset + 3] & 0xFF) << 24);
    return value;
}

public String bytesToChar(byte[] bytes){
    char[] chars = new char[bytes.length];
    for (int i = 0; i < bytes.length; i++) {
        chars[i] = (char) (bytes[i] & 0xFF); // 使用位運算將字節(jié)轉(zhuǎn)換為字符
    }

// for(int i =0;i<chars.length;i++){
// System.out.println(“char數(shù)組:”+chars[i]);
// }
String str = new String(chars);
// System.out.println(“轉(zhuǎn)換后的字符數(shù)組:” + str);
return str;
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    log.info("關(guān)閉通道");
    cause.printStackTrace();
    ctx.close();
}

/**
 * byte轉(zhuǎn)long
 * @Title: bytesToLong
 *
 * @param: @param src 源數(shù)組
 * @param: @param offset 起始偏移量
 * @return: long
 */
public static long bytesToLong(byte[] src, int offset) {
    long value = 0;
    for(int i = 0; i < 8; i++) {
        value |= ((long) (src[offset + i] & 0xFF) << (8 * i));
    }

    return value;
}
/**
 * byte轉(zhuǎn)float
 * @Title: byteToFloat
 *
 * @param: @param src 源數(shù)組
 * @param: @param offset 起始偏移量
 * @return: float
 */
public static float byteToFloat(byte[] src, int offset) {
    int value;
    value = src[offset + 0] & 0xFF;
    value |= ((long) (src[offset + 1] & 0xFF) << 8);
    value |= ((long) (src[offset + 2] & 0xFF) << 16);
    value |= ((long) (src[offset + 3] & 0xFF) << 24);
    return Float.intBitsToFloat(value);
}

/**
 * byte轉(zhuǎn)double
 * @Title: byteToDouble
 *
 * @param: @param src 源數(shù)組
 * @param: @param offset 起始偏移量
 * @return: double
 */
public static double byteToDouble(byte[] src, int offset) {
    long value = 0;
    for (int i = 0; i < 8; i++) {
        value |= ((long) (src[offset + i] & 0xff)) << (8 * i);
    }
    return Double.longBitsToDouble(value);
}


public static void main(String[] args){
    File file = new File("C:\\Users\\Administrator\\Desktop\\test.txt"); // 要讀取的文件名
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "GBK"))) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    try{
        String str = "hello";
        byte[] bytes = str.getBytes("GBK"); // 將字符串轉(zhuǎn)換為字節(jié)數(shù)組
        String newStr = new String(bytes, "GBK"); // 將字節(jié)數(shù)組轉(zhuǎn)換為字符串
        System.out.println("源字符串:"+str);
    }catch (Exception e){
        e.printStackTrace();
    }

}

}
注:其中c語言二進制字節(jié)碼int、double、float型通過位運算皆可;
而string類型轉(zhuǎn)換的時候存在亂碼,此時我是通過通配符替換掉亂碼的,就是除了中文、數(shù)字、特殊字符一律替換為空;
另外還有一個問題,就是netty的channel循環(huán)接收時,上一輪的字節(jié)數(shù)的最后不是字符的最后一位,這樣下一輪的開頭其實是一個字符剩下的部分,這時拼接轉(zhuǎn)寫也會出現(xiàn)為空的情況,這時java小端字節(jié)碼編碼方式造成的,只要規(guī)避即可。文章來源地址http://www.zghlxwxcb.cn/news/detail-831142.html

到了這里,關(guān)于Springboot使用Netty連接Tcp接口(c語言二進制字節(jié)碼轉(zhuǎn)java字符串)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • C語言文本模式和二進制模式

    本篇文章介紹一下C語言的文本模式和二進制模式 從宏觀上看,無論是文本文件還是二進制文件,文件中保存的都是 0和1的序列 ,因為磁盤只有這兩種狀態(tài)。不同的文件只是對0、1序列的解釋不同, 如果文件內(nèi)容是以字符編碼的方式保存到文件中的 ,無論是以哪種編碼方式,

    2024年02月05日
    瀏覽(19)
  • 【c語言】二進制文件的讀寫操作

    【c語言】二進制文件的讀寫操作

    創(chuàng)作不易,本篇文章如果幫助到了你,還請點贊 關(guān)注支持一下???)!! 主頁專欄有更多知識,如有疑問歡迎大家指正討論,共同進步! ??c語言系列專欄:c語言之路重點知識整合 ?? 給大家跳段街舞感謝支持!? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 本文基

    2024年02月12日
    瀏覽(23)
  • C#藍(lán)牙連接及傳輸數(shù)據(jù)的三種方式(藍(lán)牙傳輸文件、二進制數(shù)據(jù))

    C#藍(lán)牙連接及傳輸數(shù)據(jù)的三種方式(藍(lán)牙傳輸文件、二進制數(shù)據(jù))

    ? ? ? 先下載InTheHand.Net.Personal.dll并在C#中引用,這個需要在網(wǎng)上下載 ? ? ?先看界面 ? ? ? ? ? ?這種方式優(yōu)點是穩(wěn)定性較強,基本無錯誤,就是偶爾需要提前藍(lán)牙配對。 ? ? ? ?這種方式直接與藍(lán)牙設(shè)備進行配對的時候會報錯,請求的地址無效,這時候需要在被檢測的藍(lán)牙

    2024年02月11日
    瀏覽(31)
  • 【C語言】求二進制位中一的個數(shù)

    【C語言】求二進制位中一的個數(shù)

    原題鏈接:??途W(wǎng) 題目內(nèi)容: 寫一個函數(shù)返回參數(shù)二進制中 1 的個數(shù),負(fù)數(shù)使用補碼表示。 比如: 15????0000 1111????4 個 1 方法一: NumberOf1函數(shù)的實現(xiàn)比較簡單,它使用了一個循環(huán),不斷將n除以2,并判斷余數(shù)是否為1。如果余數(shù)為1,則說明n的二進制表示中最低位為1,計

    2024年02月09日
    瀏覽(26)
  • C語言二進制數(shù)據(jù)和16進制字符串互轉(zhuǎn)

    知識點:結(jié)構(gòu)體中的“伸縮型數(shù)組成員”(C99新增) C99新增了一個特性:伸縮型數(shù)組成員(flexible array member),利用這項特性聲明的結(jié)構(gòu),其最后一個數(shù)組成員具有一些特性。第1個特性是,該數(shù)組不會立即存在。第2個特性是,使用這個伸縮型數(shù)組成員可以編寫合適的代碼,就

    2024年02月13日
    瀏覽(29)
  • 【初階C語言】操作符1--對二進制的操作

    【初階C語言】操作符1--對二進制的操作

    前言:本節(jié)內(nèi)容介紹的操作符,操作的對象是二進制位。所以前面先介紹整數(shù)的二進制位 1.二進制介紹 (1)整數(shù)的二進制表示形式有三種:原碼、反碼和補碼。 (2)原碼、反碼和補碼的長度有數(shù)據(jù)類型來決定,如整數(shù),就是四個字節(jié),轉(zhuǎn)化后是三十二位比特位,所以一個整

    2024年02月09日
    瀏覽(22)
  • 實戰(zhàn)篇之基于二進制思想的用戶標(biāo)簽系統(tǒng)(Mysql+SpringBoot)

    實戰(zhàn)篇之基于二進制思想的用戶標(biāo)簽系統(tǒng)(Mysql+SpringBoot)

    ??????? 一: 計算機中的二進制 ????????計算機以二進制表示數(shù)據(jù),以表示電路中的正反。在二進制下,一個位只有 0 和 1 。逢二進一 位。類似十進制下,一個位只有 0~9 。逢十進一位。 ???????? 二: 進制常用運算 (位運算) 與運算():將兩個二進制數(shù)的對應(yīng)

    2024年02月12日
    瀏覽(21)
  • SpringBoot中使用Netty實現(xiàn)TCP通訊,服務(wù)器主動向客戶端發(fā)送數(shù)據(jù)

    SpringBoot中使用Netty實現(xiàn)TCP通訊,服務(wù)器主動向客戶端發(fā)送數(shù)據(jù)

    Springboot項目的web服務(wù)后臺,web服務(wù)運行在9100端口。 后臺使用netty實現(xiàn)了TCP服務(wù),運行在8000端口。 啟動截圖如下: 啟動類修改: 服務(wù)器查看當(dāng)前所有連接的客戶端 ?服務(wù)器獲取到所有客戶單的ip地址及端口號后,即可通過其給指定客戶端發(fā)送數(shù)據(jù) ?

    2024年02月11日
    瀏覽(29)
  • 【0到1的設(shè)計之路】從C語言到二進制程序

    【0到1的設(shè)計之路】從C語言到二進制程序

    C程序如何從源代碼生成指令序列(二進制可執(zhí)行文件) 預(yù)處理 - 編譯 - 匯編 - 鏈接 - 執(zhí)行 方法: 閱讀工具的日志(查看是否支持verbose, log等選項) 通過man gcc并搜索-I選項可得知頭文件搜索的順序 好的編程習(xí)慣 - 總是用括號包圍參數(shù) 好的編程習(xí)慣 - 一個參數(shù)盡量不要展開多次 上述

    2024年01月23日
    瀏覽(71)
  • C語言:二進制、八進制、十六進制整數(shù)的書寫及輸出

    C語言:二進制、八進制、十六進制整數(shù)的書寫及輸出

    目錄 一、整型數(shù)據(jù)類型 二、二進制、八進制、十六進制的書寫 1)二進制 以 0b / 0B 開頭,不區(qū)分大小寫(數(shù)字0,而非字母o,下同) 2)八進制 以數(shù)字 0 開頭 ????????3)十六進制 以 0x / 0X 開頭, 三、二進制、八進制和十六進制的輸出 八進制? ?(%o): 十六進制? ?(%x):

    2024年02月05日
    瀏覽(99)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包