java - C客户端套接字数据无法在Java服务器中读取
问题描述
当 bytearray 转换为字符串时,Java 服务器套接字给出错误的输出。C套接字头格式
int tccode 4
int len 4
char data[4088] 4088
C结构格式
Tc Code :1001 Size : 256
#ifdef __DTGPL1T__
struct DTGPL1T_S
{
// ENTRY ZONE
short por1cur;
short por2cur;
short por1ten;
short por2ten;
short p1lvim1;
short p1lvim2;
short p1lvim3;
short p2lvim1;
short p2lvim2;
short p2lvim3;
short brc1 ;
short entrylt; short enlopcar;
short notchlen;
short poruse;
short p1remain;
short p2remain;
short eloopcap;
short elooplen;
short untielen;
short entryspd;
short st8ten;
short brc2 ;
short scbtns;
short scbel ;
short scb1intr;
short scb2intr;
short scb3intr;
short st3ten;
short brc3 ;
short plettkts;
short deli1ten;
short d1loopcc;
short d1loopln;
short d1loopcp;
short brc4 ;
short br4ten;
short plcspd;
short triwidt;
short sthosingwidth ;
short trigap1;
short trigap2;
short trigap3;
short trigap4;
short trilap1;
short trilap2;
short trilap3;
short trilap4;
short aactwid;
short adevwid;
short chopw ;
short chopd ;
short tristat;
short trispd;
short trmtoplen;
short deli2ten;
short d2loopcc;
short d2loopcp;
short d2loopln;
short br5ten;
short brc5 ;
short wpd1sta;
short wpd2sta;
short wpd3sta;
short wpd3asta;
short wpd4sta;
short wpd5sta;
short chvsen[2];
short wbsen[2];
short etcsen;
short wpdpass[6];
short wpdlen[6];
short pl_cv_next_move;
short ccv1_lock_curr ;
short ccv2_lock_curr ;
short ewb1_lock_curr ;
short ewb2_lock_curr ;
short etc_lock_curr ;
short eskd1_lock_curr;
short eskd2_lock_curr;
short ecc1_lock_curr ;
short ecc2_lock_curr ;
short st_wid_low_err ;
short st_wid_upp_err ;
short trim_width_set;
short hadling_time;
short spare01[14] ;
short spare02[16] ;
//38 + 16 = 53
};
typedef struct DTGPL1T_S DTGPL1T_T;
typedef DTGPL1T_T *DTGPL1T_P;
#define DTGPL1T_LN sizeof(DTGPL1T_T)
#endif // Eof of __DTGPL1T__
和 Java 服务器代码
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
//DataInputStream in = new DataInputStream(new BufferedInputStream(clientSocket.getInputStream()));
int tcCode = in.readInt();
int length = in.readInt();
if(tcCode == 1001) {
byte[] messageByte = new byte[length];
boolean end = false;
StringBuilder dataString = new StringBuilder(length);
int totalBytesRead = 0;
while(!end) {
int currentBytesRead = in.read(messageByte);
totalBytesRead = currentBytesRead + totalBytesRead;
if(totalBytesRead <= length) {
dataString
.append(new String(messageByte, 0, length - totalBytesRead + currentBytesRead));
} else {
dataString
.append(new String(messageByte, 0, length - totalBytesRead + currentBytesRead));
}
if(dataString.length()>=length) {
end = true;
}
}
System.out.println("Message1 "+dataString);
}
MessageBytes 变得像[-1, -2, 0, 0, 0, 0, 0, 0, 0, 35, 0, 33, 0, 30, 0, 45, 0, 40, 0, 35, 0, 0, 0, 0, -1, -1, 0, 10, 0, 1, 0, 1, 0, 1, 5, -123, 0, 111, 3, 34, 0, 0, 0, 0, 0, 0 , 2, -25, 0, 24, -1, -2, -1, -3, 0, 0, 0, 0, 0, 0, 43, 37, -1, -35, 0, 0, 0, 72, 10, 42, 0, 0, 43, 37, 0, 0, 49, 126, 112, -30, 0, 5, 0, 5, 0, 11, 0, 12, -3, 68, -3 , 68, -6, -20, -6, -20, 27, 86, 0, 0, 0, 16, 0, 16, 0, 0, 0, 0, 0, -13, -1, -7, 0, 0, 16, 107, 0, -99, 0, 80, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -20, 4, -73, -1, 74, -1] [输出截图] 1
解决方案
与 C 不同,Java 字符串不适合保存字节。将字节转换为字符串会解码字节,这意味着某些值可能会被更改或丢失。
即使没有更改任何值,您的数据也不会代表字符,因此将其打印为文本将显示无意义。例如,您的许多字节都是零,这根本不会显示在输出中,因为字符\u0000
是非打印控制字符。
您应该完全避免使用 Strings 和 StringBuilders。相反,仅将字节存储在字节数组中:
while (totalBytesRead < length) {
int currentBytesRead = in.read(messageByte,
totalBytesRead, length - totalBytesRead);
totalBytesRead = currentBytesRead + totalBytesRead;
}
您的数据似乎完全由short
值组成,因此,假设 C 客户端被构建为short
视为 16 位值,并且假设 C 编译器没有填充您的struct
成员以对它们进行字对齐,您可以转换您的字节使用ByteBuffer和ShortBuffer到一系列短裤:
ByteBuffer buffer = ByteBuffer.wrap(messageByte);
ShortBuffer shortBuffer = buffer.asShortBuffer();
要打印它们,请将它们作为数组检索并使用Arrays.toString:
short[] values = new short[length / 2];
shortBuffer.get(values);
System.out.println(Arrays.toString(values));
推荐阅读
- r - 在分组的数据框列表上使用 lapply
- c# - 将文件加载为字节数组,而不在内存中分配它 C#
- android - 为什么 Android BillingClient v2 慢速信用卡测试永远不会取消?
- python - 可以通过“conda install”命令安装所有“pip”包吗?
- c# - 循环此 switch case 语句时遇到问题
- javascript - Javascript 中的 click 函数出错
- c# - Azure Functions 3.0 部署时随机抛出运行时错误
- javascript - 在 JavaScript 中过滤嵌套对象
- python - 尝试开发二十一点游戏的计分系统
- c# - .NET Core 3.1/IHostBuilder 的 UseUrls 等效项