最近开发物联网项目,由于人员变动,之前的接口无法使用,只能重新开发,最近今天测试OK了,拿出来和大家分享一下。
由于对JAVA比较熟悉,所以本次使用JAVA开发TCP协议接口,这个开发比较方便,不需要引入任何其他的jar包,运行时标准jvm就可以。
闲话少说,上代码
1,多线程主程序
public class TcpMainTest extends Thread{
Socket clientSocket;
public TcpMainTest(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
try {
// 设置5分钟超时
this.clientSocket.setSoTimeout(5 * 60 * 1000);
// 获取客户端来的数据
char[] a = new char[100];
String str = "";
while(true){
BufferedReader in = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
in.read(a);
str = new String(a);
// 清除数组中多余的内容
str = str.replace("\0", "");
System.out.println("received message:" + str);
// 因为有心跳指令干扰,必须保证收到login信息
if (str.contains("login")) {
break;
} else {
try{
this.clientSocket.close();
} catch(IOException e) {
System.out.println("connection closed!");
}
}
}
// 返回的信息中有login的话,属于登录等成功
if (str.contains("login")) {
String sn = "";
JSONObject jo = JSONObject.parseObject(str);
sn = jo.getString("sn"); //设备编号
while(true){
// 发送指令
byte[] s = Util.hexStrToBinaryStr("010300012342C40B");
this.clientSocket.getOutputStream().write(s);
// 接收信息
byte[] rsByte = new byte[100];
this.clientSocket.getInputStream().read(rsByte);
String recMsg = Util.BinaryToHexString(rsByte);
// 以02 02 03开头的信息为数据信息
if(recMsg.startsWith("02 02 03")){
// 清除16进制字符串中的空格
recMsg = recMsg.replace(" ", "");
// 截取出温度和湿度
String temperatureHex = recMsg.substring(6, 10);
String humidityHex = recMsg.substring(10, 14);
System.out.println(sn + " / " + "Tem:" + temperatureHex + " / " + "Hum:" + humidityHex);
}
// 每次休眠1秒钟
Thread.sleep(1000);
}
}
} catch (Exception e) {
System.out.println("发生错误:" + e.getMessage());
try {
this.clientSocket.close();
} catch (IOException e1) {
System.out.println("Socket关闭发生错误:" + e1.getMessage());
}
}
}
public static void main(String[] args) throws IOException {
System.out.println("服务已启动, 等待连接!");
//建立TCP连接服务,绑定端口
ServerSocket tcpServer = new ServerSocket(7777);
//接受连接,每个TCP连接都是一个java线程
while(true){
Socket clientSocket = tcpServer.accept();
new TcpMainTest(clientSocket).start();
}
}
}
2,Util工具类
public class Util {
// 将16进制的字符串转换成字节数组
public static byte[] hexStrToBinaryStr(String hexString) {
hexString = hexString.replaceAll(" ", "");
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;
}
// 将字节数组转换为16进制字符串
public static String BinaryToHexString(byte[] bytes) {
String hexStr = "0123456789ABCDEF";
String result = "";
String hex = "";
for (byte b : bytes) {
hex = String.valueOf(hexStr.charAt((b & 0xF0) >> 4));
hex += String.valueOf(hexStr.charAt(b & 0x0F));
result += hex + " ";
}
return result;
}
}
3,因为设置了setSoTimeout(5 * 60 * 1000),所以超过5分钟没有消息,长连接会自动断开(报read time out错误),等待设备再次发送登录报文。
4,上面的程序经过多日的试验,无论稳定性,还是断点续连都是可以的,分享给大家,一起共勉。