终端参数上报后,平台通过tcp协议接收到相应数据并处理。
终端将终端参数以json格式的数据发送至平台。终端上电后上报,可以不认证直接上报。
实现流程如下。
1.设置终端参数上报的协议类型,例如:0x0000。
public static final int CMD_UP_PARAM = 0x0000;
2.侦听tcp服务
public void startServer() {
log.info("startServer begin,tcp port={}", port);
//处理接收accept连接的线程池
EventLoopGroup bossGroup = new NioEventLoopGroup();
//处理tcp接收到的数据的线程池
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
b.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);// 关键是这句
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch)
throws Exception { InetSocketAddress insocket = (InetSocketAddress)ch.localAddress();
// 注册OutboundHandler,执行顺序为注册顺序的逆序
ch.pipeline().addLast(new ProtocolEncoder());
// 注册InboundHandler,执行顺序为注册顺序
//tcp连接始终 120秒 没收到数据 300毫秒未发送数据
ch.pipeline().addLast(new IdleStateHandler(120000, 0, 0, TimeUnit.MILLISECONDS));
//根据不同的侦听端口,采用不同的解码类
ch.pipeline().addLast(new ProtocolDecoder());
ch.pipeline().addLast(new DiffChannelLogin());
ch.pipeline().addLast(new DealProtocolData()); } }).option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
log.info("startServer bind,tcp port={}", port);
ChannelFuture f = b.bind(port).sync();
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
log.error("InterruptedException e={}", e);
} finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
log.info("startServer end,tcp port={}", port);
}
}
3.处理接收到的tcp数据,该数据是登录认证后的数据。
处理完成后,将结果响应给终端。4位处理代码。
ProtDataApi diffProtocol(ChnlData chl, ProtDataApi protData) {
if (protData instanceof ProtDataString) {//instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
return diffProtocolString(chl, protData);
} ProtData data = (ProtData) protData;
//log.info("diffProtocol,json={}", data.jsontext);
JSONObject json = JSON.parseObject(data.jsontext);
JSONObject res = null; if (data.getCmd() == DeviceProtCmd.CMD_UP_LOGIN) {
res = service.logIn(chl, json);
if (res == null) {
chl.close();
return null;
}
} else if(data.getCmd() == DeviceProtCmd.CMD_UP_PARAM){ } else if (chl.getData() instanceof DeviceData == false){
chl.close();
return null;
} long context = json.getLongValue("context");
if (context > 0) { } taskDao.recvDevTaskData(data.getCmd(), json); DeviceData dev = (DeviceData) chl.getData();
if (dev != null) {
ProtDataApi d = dao.updateTaskFlag(dev.getId(), json);
if (d != null) {
return d;
}
}
switch (data.getCmd()) {
case DeviceProtCmd.CMD_UP_PARAM:
res = service.uploadParam(chl, json);
break;
default:
break;
} if (res == null) {
return null;
} return new ProtData(data.getCmd(), data.getSessionId(), res.toJSONString(), chl.getEncoding());
}
4.平台处理接收到的终端参数,并更新入库,响应结果。
public JSONObject uploadParam(JSONObject json) throws Exception {
String identity = json.getString("identity");// ”:”设备序列号”,
int id = dataDao.getDeviceId(identity);
if (id == -1) {
log.error("该设备,identity={},不存在!", identity);
return JsonUtils.getErrorJson(ErrorCode.ERR_NORECORD);
} String modelno = json.getString("modelno");//":"KCC(1A)", //设备型号
String devtype = json.getString("devtype");//":"1011", //设备类型
String hardver = json.getString("hardver");//":"硬件版本",
String softver = json.getString("softver");//":"软件版本",
String serverip = json.getString("serverip");//":"平台ip",
String serverport = json.getString("serverport");//":"平台端口号",
String sql = "update info_terminal set devModel=?,devicetypeid=?,hardver=?"
+ ",softver=?,platform_ip=?,platform_port=? where id=?";
JSONObject res;
try {
jt.update(sql, modelno,devtype,hardver,softver,serverip,serverport,id);
res = JsonUtils.getErrorJson(ErrorCode.ERR_SUCCESS);
} catch (DataAccessException e) {
log.error("更新参数失败,sql={},json={},exception={}", sql, json.toJSONString(), e);
res = JsonUtils.getErrorJson(ErrorCode.ERR_SAVE);
}
return res;
}
5.回应终端数据处理
public short head;//协议头
public int cmd;//协议类型
public int sessID;//会话id
public short pkgID;//包号
public short pkgCount;//总包数
public short keyID;//密钥id
public short datalen;//单包数据长途
public int totalLen;//数据总长度
public byte[] data;//数据
private ChannelHandlerContext ctx;
public String jsontext;//json字符串
private String encoding; public ProtData(int cmd, int sessID, String jsontext, String encoding){
this.encoding = encoding;
this.head = 0x2324;
this.cmd = cmd; this.sessID = sessID;
pkgCount = 1;
pkgID = 0;
keyID = (short) DeskeyConfig.getKeyId();
datalen = 0;
data = new byte[datalen];
DecryptionMode jm = DecryptionMode3DesImp.getDecryptionMode();
data = jm.getDecryption(data, sessID, keyID);
this.jsontext = jsontext;
}
6.附上协议。
json格式如下:
{
"identity":"设备序列号",
"modelno":"kcc(1a)", //设备型号
"devtype":1011, //设备类型
"hardver":"硬件版本",
"softver":"软件版本",
"serverip":"平台ip",
"serverport":平台端口号
}
应答:
字段名 长度 备注
json n json格式的数据 json格式如下:
{
"errcode":错误码
}
终端参数上报后,平台通过tcp协议接收到相应数据并处理。的更多相关文章
- 【转】使用TCP协议连续传输大量数据时,是否会丢包,应如何避免?
使用TCP协议连续传输大量数据时,是否会丢包,应如何避免? 比如发送文件.记得有人提过可能会发生什么堆栈溢出.怎样避免呢?是不是可以收到数据后发送确认包,收到确认包后再继续发送.或是发送方发送了一些数 ...
- 【Java】学习路径60-利用TCP协议接收多个客户端的数据
import java.io.IOException; import java.net.*; public class TCP_Server { public static void main(Str ...
- Python3的tcp socket接收不定长数据包接收到的数据不全。
Python Socket API参考出处:http://blog.csdn.net/xiangpingli/article/details/47706707 使用socket.recv(pack_l ...
- java-UDP协议接收和发送数据
UDP发送数据的步骤: A:创建发送端的Socket服务对象 B:创建数据,并把数据打包 C:通过Socket对象的发送功能发送数据包 D:释放资源 public class SendDemo { ...
- (Tcp协议)linux上netstat -atunlp后出现的数据的意思(socket状态)
https://zhidao.baidu.com/question/486077599.html 1.netstat命令的-t参数指的是 tcp的简写,意思是仅显示tcp相关选项2.示例:列出所有 t ...
- (2)socket的基础使用(基于TCP协议)
socket()模块函数用法 基于TCP协议的套接字程序 netstart -an | findstr 8080 #查看所有TCP和UDP协议的状态,用findstr进行过滤监听8080端口 服务端套 ...
- 【TCP协议详解】
为什么会有TCP/IP协议 在世界上各地,各种各样的电脑运行着各自不同的操作系统为大家服务,这些电脑在表达同一种信息的时候所使用的方法是千差万别.就好像圣经中上帝打乱了各地人的口音,让他们无法合作一样 ...
- Linux 高性能服务器编程——TCP协议详解
问题聚焦: 本节从如下四个方面讨论TCP协议: TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流 TCP状态转移过程:TCP连接的任意一 ...
- 【转】运输层TCP协议详细介绍
TCP是TCP/IP协议族中非常复杂的一个协议.它具有以下特点: 1:面向连接的运输层协议.在使用TCP协议之前,首先需要建立TCP连接.传送数据完毕后,必须释放已经建立的TCP连接. 2:一条TCP ...
随机推荐
- 重绘ComboBox —— 让ComboBox多列显示
最近在维护一个winform项目,公司购买的是DevExpress控件 (请问怎么联系DevExpress工作人员? 我想询问下,广告费是怎么给的.:p),经过公司大牛们对DevExpress控件疯狂 ...
- CentOS7搭建Docker镜像实战
开发十年,就只剩下这套架构体系了! >>> 一.搭建环境 使用的是VMWare 12虚拟机安装的CentOS7 安装成功后修改ip: 1. ip addr查看相关信息: 2. 修 ...
- C# 实现实体类和Xml转换
一.实体类转换成XML 将实体类转换成XML需要使用XmlSerializer类的Serialize方法,将实体类序列化 public static string XmlSerialize<T& ...
- ps:图像格式的选择
从上面点阵与矢量两者的对比中,似乎矢量格式有优势,那为什么不都使用矢量格式呢? 这是因为矢量图像是基于线段的.因此它不适合记录色彩较为复杂的图像.如下图, 如果使用点阵方式来记录,只要按照顺序扫描并记 ...
- vue 概念与使用vue-cli脚手架快速构建项目
vue 定义:是一套构建用户界面的渐进式框架,Vue 采用自底向上增量开发的设计.Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合. 数据渲染机制: 核心: 响应式数据绑定 ...
- Ts 的类
TS 中的公共.私有和受保护的修饰符: 1.public表示公共的,用来指定在创建实例后可以通过实例访问的,也就是类定义的外部可以访问的属性和方法.默认是 public 2.private修饰符表示私 ...
- bzoj3589 动态树 树链剖分+容斥
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3589 题解 事件 \(0\) 不需要说,直接做就可以了. 事件 \(1\) 的话,考虑如果直接 ...
- django之csrf_exempt解决跨域请求的问题
一: from django.views.decorators.csrf import csrf_exempt # 获取微信返回的code信息 @csrf_exempt def wechat_auth ...
- C语言版本学生信息管理系统
仍然有一些小bug,后续会发布OC完善版的图书馆管理系统,欢迎批评指正. #include <stdio.h> void menu_choose(); typedef struct { i ...
- Hadoop 学习目录(搁置)
简介 Hadoop是一个由Apache基金会所开发的分布式系统基础架构.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力进行高速运算和存储.Hadoop实现了一个分布式文件系 ...