基于Socket的java实现tcp协议与开发板传输数据,问题解
由于开发板传来的数据是无符号位的,而上一篇文章中的byte是有符号的所以这样读出来的的数据是不准确的,现做如下更改:
1.需求分析:开发板发出十六进制的数据.而我之前用java接收的显示出来是10进制,所以如果跟开发要求中的数据分析会比较难以观察,无法判断.
比如规定,所有的数据都遵循如下规定:帧头1字节(A3) ,保留3字节,地址字段8字节,命令长度2字节,命令数据(0-200字节)校验,1字节
但从开始的帧头1字节A3这里显示就有问题,这里输出是10 03 是两个字节,因为A3无符号显示是163的十进制,显然大于byte的上限127,所以它分成了A和3来写,就算进行不进行无符号的处理由于A3的二进制(1010 0011)也会当成是负数来处理,所以一定要用无符号的判断方式.
Inputstream 读取的是有符号的byte数据,且,缓存在byte[]数组中也必须给byte大小,而显然这里可以看到贵的的长度是不定的.所以我用DataInputStream来实现无符号位数据处理.
1.DataInputStream 是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”。应用程序可以使用DataOutputStream(数据输出流)写入由DataInputStream(数据输入流)读取的数据。
其中有三个方法都是支持无符号位的数据
(1)int readUnsignedByte() //从流中读取一个0~255(0xFF)的单字节数据,并以int数据类型的数据返回。返回的数据相当于C/C++语言中所谓的“BYTE”。
(2)int readUnsignedShort() //从流中读取一个0~65535(0xFFFF)的双字节数据,并以int数据类型的数据返回。返回的数据相当于C/C++语言中所谓的“WORD”, 并且是以“低地址低字节”的方式返回的,所以程序员不需要额外的转换。
(3) String readUTF() //这个我试验失败了,就不做多说了
public String getReceiveOne(DataInputStream input) throws Exception
{
int receiveBytes = input.readUnsignedByte();//这里是一个字节一个字节读取的
String receiveOne = Integer.toHexString(receiveBytes);//还原读取额数据为16进制
return receiveOne;
}
这样用工具输入测试数据A3的时候一定要选择16进制显示,要不然你输出的还是乱码,
微信截图_20180726155253.png
2.解决数据长度不定的问题
由于这里规定了每一位数据代表的意义,其中命令长度两个字节包含了:命令数据长度,所以这数据长度不定主要是命令数据长度是变化的但是命令总长是给出了的那么就好处理了.
创建一个类,接受数据类.将不同意义的字段作为变量,然后接收数据的时候就
public class ReceiveMessage
{
public static String SY = null;//1
public static String RE = null;//3
public static String ADDRESS = null;//8
public static String SL = null;//2
public static String DATA = null;//1-200
public static String CR = null;//1
public static String printString()
{
return "ReceiveMessage{" + SY + " " + RE + " " + ADDRESS + " " + SL + " " + DATA + " " + CR + " " + '}';
}
}
读取数据的时候分别存入对应位置
//无符号位处理无符号位数据处理
public void getReceveMesssageNoSymbol(DataInputStream in) throws Exception
{
int count = 1;
switch (count) {
case 1:
String message = getReceiveOne(in);
if(!message.equals("s3")){break;}//不是s3开始就结束
ReceiveMessage.SY = message;
count = count + 1;
}
case 2:
ReceiveMessage.RE = getReceiveOne(in);
count += 1;
while (count < 5) {
ReceiveMessage.RE = ReceiveMessage.RE + " " + getReceiveOne(in);
count += 1;
}
case 5:
ReceiveMessage.ADDRESS = getReceiveOne(in);
count += 1;
while (count < 13) {
ReceiveMessage.ADDRESS = ReceiveMessage.ADDRESS + " " + getReceiveOne(in);
count += 1;
}
case 14:
ReceiveMessage.SL = getReceiveOne(in);
count += 1;
while (count < 16) {
ReceiveMessage.SL = ReceiveMessage.SL + " " + getReceiveOne(in);
count += 1;
}
case 16:
ReceiveMessage.DATA = getReceiveOne(in);
int length = Integer.parseInt((ReceiveMessage.SLEN).replace(" ", ""), 16);//取出总长度
length = count + length - 1;//由于上面已经自增1了所以这里减去1.
while (count < length) {
ReceiveMessage.DATA = ReceiveMessage.DATA + " " + getReceiveOne(in);
count += 1;
}
ReceiveMessage.CRC = getReceiveOne(in);//最后加上校验位
log.info(ReceiveMessage.printString());
break;
}
}
这样写完测试数据是不能随便写了,要不然就出现各种问题:
S3 000000 9000000000000000 000E 0902000000000000000090000000 1a
测试的时候记得把测试数据的空格去掉.要不然数据会溢出.