c 和java通讯大小端问题处理_记录一个如何解决java与C++socket通信的大小端问题...
問題背景
oracle jdk默認的socket通信發送int類型數據高位優先。下面是jdk包內部相關源碼。(模擬)os.write((len?>>>?24)?&?0xFF);os.write((len?>>>?16)?&?0xFF);os.write((len?>>>?8)?&?0xFF);os.write((len?>>>?0)?&?0xFF);
可以很明顯的看出寫入流時,先右移了24位。因為int類型的數據在jdk中是以4個字節表示的。1個字節有擁有8位。這是如果按照這個順序與C++通信會發生誤讀情況,轉成10進制以后,數字完全變了。故而要調整jdk源碼。如下方法所示:/**
*?字節序轉換發送到server
*?針對發送int類型數據
*/
public?void?intTrans(int?length,?OutputStream?os)?throws?IOException?{
os.write((length?>>>?0)?&?0xFF);
os.write((length?>>>?8)?&?0xFF);
os.write((length?>>>?16)?&?0xFF);
os.write((length?>>>?24)?&?0xFF);
}
其他整型可類比。long型是8字節。
當然,同時做socket通信時,服務端接收時,協議所定義的包頭大小很顯然也是要做同樣的大小端問題處理。原理一樣。下面貼出了我的服務端代碼:import?org.slf4j.Logger;import?org.slf4j.LoggerFactory;import?org.springframework.beans.factory.annotation.Value;import?org.springframework.boot.ApplicationArguments;import?org.springframework.boot.ApplicationRunner;import?org.springframework.core.annotation.Order;import?org.springframework.stereotype.Component;import?java.io.*;import?java.net.ServerSocket;import?java.net.Socket;/**
*?@author?Jerry
*?@date?2018/11/6
*/@Component@Order(value?=?1)public?class?SocketServer?implements?ApplicationRunner?{????private?static?Logger?logger?=?LoggerFactory.getLogger(SocketServer.class);????/**
*?取到客戶端發來的int類型的消息頭,并且解決JDK大小端問題
*?@param?b
*?@return
*/
private?static?int?byteArrayToInt(byte[]?b){????????return?b[0]&0xFF?|?(b[1]&0xFF)?<
}????@Value("${pixelMaster.listen.port}")????private?int?port;????public?void?startSocketServer()?throws?IOException?{
ServerSocket?serverSocket?=?new?ServerSocket(port);????????while?(true){
Socket?client?=?serverSocket.accept();????????????new?HandlerThread(client);
}
}????private?class?HandlerThread?implements?Runnable{????????private?Socket?socket;????????private?HandlerThread(Socket?client){
socket?=?client;????????????new?Thread(this).start();
}????????@Override
public?void?run()?{????????????try{
InputStream?input?=?socket.getInputStream();????????????????byte[]?datalen?=?new?byte[4];
input.read(datalen);????????????????int?length?=?byteArrayToInt(datalen);
logger.info("客戶端發來的消息長度是:"+length);????????????????byte[]?data?=?new?byte[length];
input.read(data);
String?recvMsg?=?new?String(data);//將獲得數據轉為字符串類型
logger.info("客戶端發來的信息是:"+recvMsg);
input.close();
}catch?(Exception?e){
e.printStackTrace();
logger.error("獲取客戶端信息異常");
}
}
}????@Override
public?void?run(ApplicationArguments?args)?throws?IOException?{
startSocketServer();
}
}
順便也貼出客戶端代碼留作記錄。import?com.mcwl.pixelmaster.utils.ByteOrderTransAndSend;import?org.springframework.beans.factory.annotation.Value;import?org.springframework.stereotype.Component;import?java.io.IOException;import?java.io.OutputStream;import?java.io.PrintWriter;import?java.net.Socket;/**
*?@author?Jerry
*?@date?2018/11/1
*?描述:socket連接客戶端
*/@Componentpublic?class?Client?{????//服務器地址
@Value(value?=?"${pixelMaster.server.url}")????private?String?ipAddr;????//服務器端口
@Value(value?=?"${pixelMaster.server.port}")????private?int?port;????public?void?send(String?message)throws?IOException{
Socket?socket?=?new?Socket(ipAddr,port);
OutputStream?os?=?socket.getOutputStream();
ByteOrderTransAndSend?trans?=?new?ByteOrderTransAndSend();
trans.intTrans(message.getBytes().length,os);
PrintWriter?writer?=?new?PrintWriter(os);
writer.write(message);
writer.flush();
socket.shutdownOutput();
}
}
作者:樂樂J
鏈接:https://www.jianshu.com/p/0d3d784538f3
總結
以上是生活随笔為你收集整理的c 和java通讯大小端问题处理_记录一个如何解决java与C++socket通信的大小端问题...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 异常 最佳实践_关于JAVA异
- 下一篇: layui表单mysql_layui表单