TCP通信实现对接硬件发送与接收⼗六进制数据int与byte的
转换原理java中正负数的表⽰
   今天收到的⼀份需求任务是对接硬件,TCP通信,并给出通信端⼝与数据包格式,如下:
1.⾸先编写了⼀个简单的⼗六进制转byte[]数组与byte[]转换16进制字符串的两个⽅法,如下:
/**
* 将⼗六进制的字符串转换成字节数组
*
* @param hexString
* @return
*/
public static byte[] hexStrToByteArrs(String hexString) {
if (StringUtils.isEmpty(hexString)) {
return null;
}
hexString = placeAll(" ", "");
int len = hexString.length();
int index = 0;
byte[] bytes = new byte[len / 2];
while (index < len) {
String sub = hexString.substring(index, index + 2);
bytes[index / 2] = (byte) Integer.parseInt(sub, 16);
index += 2;
}
return bytes;
}
/**
* 数组转换成⼗六进制字符串
*
* @param byte[]
* @return HexString
*/
public static final String bytesToHexString(byte[] bArray) {
StringBuffer sb = new StringBuffer(bArray.length);
String sTemp;
for (int i = 0; i < bArray.length; i++) {
sTemp = HexString(0xFF & bArray[i]);
if (sTemp.length() < 2)
sb.append(0);
sb.UpperCase());
}
String();
}
测试:
String string = "C0 10 00 00 00 02 04 00 01 00 00 a2 6f";
byte[] bs = { -64, 16, 0, 0, 0, 2, 4, 0, 1, 0, 0, -94, 111 };
System.out.String(hexStrToByteArrs(string)));
System.out.println(bytesToHexString(bs));
结果:
[-64, 16, 0, 0, 0, 2, 4, 0, 1, 0, 0, -94, 111]
C010000000020400010000A26F
补充:这⾥说明⼀下简单的⼗六进制转byte与byte转⼗六进制的⽅法:
以⼗六进制的 C0,也就是⼗进制的192为例⼦。
数组格式字符串转数组(1)⼗六进制转byte:
// 1.先转为In类型
int parseInt = Integer.parseInt("c0", 16);
/
/ 2.强转为byte
byte b = (byte) parseInt;
System.out.println(parseInt);
System.out.println(b);
结果:
192
-64
在这⾥也明⽩了实际我们调⽤Integer.parseInt(str)的时候默认传的是⼗进制,如下:
public static int parseInt(String s) throws NumberFormatException {
return parseInt(s,10);
}
注意:
int占4个字节,byte占1个字节,1个字节占8位,那么强制类型转换int型截取低8位,对数据也不会造成影响。
如果再从byte型转换成int型呢。int强制转换为byte型数据时,会产⽣⼀个-128~127的有符号字节,所以byte转int的时候需要根据符号判断。
如下:
int intNum = 192;
byte byteNum = (byte) intNum;
int intNum2 = byteNum;
System.out.println(intNum);
System.out.println(byteNum);
System.out.println(intNum2);
结果:
192
-64
-64
正确的byte转int是需要考虑byte的符号的,如下:
int intNum = 192;
byte byteNum = (byte) intNum;
int intNum2 = byteNum > 0 ? byteNum : byteNum + 256;
System.out.println(intNum);
System.out.println(byteNum);
System.out.println(intNum2);
结果:
192
-64
192
计算机表⽰正负数(想着明⽩⼀下转换原理)
关于计算机表⽰正负数的⽅法:
  1. 负数在计算机中的表⽰为取反+1,取反+1成为这个数的⼆进制补码。
  2.最⾼位为符号位,1负,0正。
以上⾯的int类型192为例⼦,其⼆进制表⽰为:(前⾯的xxx表⽰24个0,也就是前⾯3个byte都是0)
<(24个0)    11000000
其转换为byte之后是舍掉前3byte,取低⼋位,就只剩下 11000000。
11000000:  由于第⼀位是符号位,1代表负数,所以其计算⽅法是取反加1 (取反之后是: 00111111,加1之后是01000000),转换为⼗进制就是 -64 。
再以⼗进制的128为例⼦:
其int型位数如下:    (24个0) 10000000
转换为byte之后为 10000000
由于1表⽰为负数,所以先取反为01111111,再加上00000001之后就是10000000,计算结果就是-128。
int intNum = 128;
byte byteNum = (byte) intNum;
int intNum2 = byteNum > 0 ? byteNum : byteNum + 256;
System.out.println(intNum);
System.out.println(byteNum);
System.out.println(intNum2);
结果:
128
-128
128
(2)byte转16进制的字符串
byte b = -64;
int intNum2 = b > 0 ? b : b + 256;
String string = String(intNum2, 16);
System.out.println(string);
结果:
c0
  这⾥需要明⽩:byte转为int需要根据符号进⾏转换,原因参考上⾯的补充;然后调⽤String(num,radix)即可实现int转换⼗六进制字符串。
2.Java实现TCP协议发送⼗六进制数据(将⼗六进制数据转换为byte[])和接收byte 数据并转成16进制字符串
服务端:(也就是模拟硬件,接受byte[]数据并转成16进制)
package zd.dms.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.ServerSocket;
import java.Socket;
import java.util.Arrays;
public class Server {
public static void main(String[] args) throws IOException {
// 1:建⽴服务器端的tcp socket服务,必须监听⼀个端⼝
ServerSocket ss = new ServerSocket(24992);
// 2: 通过服务器端的socket对象的accept⽅法获取连接上的客户端对象
Socket s = null;
// 3:获取客户端的数据
while (true) {
// 接受Socket服务,如果有,没有则堵塞,等待
s = ss.accept();
System.out.println("");
try {
// 从Socekt输⼊流中获取客户端发送过来的输出流
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println("从客户端传送来的数据如下:");
System.out.String(buf));
// 通过服务器端Socket输出流,写数据,会传送到客户端Socket输⼊流中
OutputStream out = s.getOutputStream();
String retunStr = "C0 01 01 03 FF 00 C0";
out.write(SocketUtils.hexStrToByteArrs(retunStr));
} catch (Exception e) {
System.out.println("error");
} finally {
s.close();
}
}
}
}
客户端:模拟发送⼗六进制数据并且接收⼗六进制数据
package zd.dms.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.Socket;
import org.apachemons.lang.math.NumberUtils;
import org.apachemons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import zd.fig.SystemConfigManager;
public class SocketUtils {
private static final Logger LOGGER = Logger(SocketUtils.class);
private static Socket socket = null;
private static String archivesCenterAPIIP = StringUtils
.Instance().getECMProps("archivesCenterAPIIP"), "127.0.0.1"); private static String archivesCenterAPIPort = StringUtils
.Instance().getECMProps("archivesCenterAPIPort"), "24992"); public static boolean connection() {
if (socket != null) {
return true;
}
try {
socket = new Socket(archivesCenterAPIIP, Int(archivesCenterAPIPort));
return true;
} catch (Exception e) {
<("connection error", e);
return false;
}
}
public static void stop() {
try {
if (socket != null) {
socket.close();
socket = null;
}
} catch (Exception e) {
<("connection error", e);
}
}
/**
* 发送数据
*
* @param cmd
*            需要发送的数据(⼗六进制的字符串形式)
* @return接受到的数据(⼗六进制的字符串形式)
*/
public static String sendCmd(String cmd) {
if (!connection() || socket == null) {
return "error";
}
try {
OutputStream out = OutputStream();
byte[] hexStrToByteArrs = hexStrToByteArrs(cmd);
if (hexStrToByteArrs == null) {
return "error";
}
out.write(hexStrToByteArrs);
InputStream in = InputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
stop();
return bytesToHexString(buf);
} catch (IOException e) {
<("sendCmd error", e);
return "error";
}
}
/**
* 将⼗六进制的字符串转换成字节数组
*
* @param hexString
* @return
*/
public static byte[] hexStrToByteArrs(String hexString) {
if (StringUtils.isEmpty(hexString)) {
return null;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。