当前位置: 首页 > news >正文

石家庄网站制作网站广州网页制作

石家庄网站制作网站,广州网页制作,本地打开wordpress,广州市天河区1、背景 tcp传输的时候会自动拆包,因此服务端接收的数据段可能跟客户端发送过来的数据段长度不一致,比如客户端一次发送10000个字节。但是服务端接收了两次才接收完整(例如第一次接收6000字节,第二次接收4000字节)。但…

1、背景

tcp传输的时候会自动拆包,因此服务端接收的数据段可能跟客户端发送过来的数据段长度不一致,比如客户端一次发送10000个字节。但是服务端接收了两次才接收完整(例如第一次接收6000字节,第二次接收4000字节)。但是服务端每次必须要接收完所有的字节才能进行处理,而且客户端每次发的数据长度都不一致。
于是经过协商,客户端每次发送数据段时,在数据段前加10个字节(后面统一称数据包头),前6个字节为数据包起始标识符,后4个字节为此次发送数据段的长度。

2、难点

因为tcp会拆包,所以数据段前的10个字节可能会出现在任何位置,也可能会出现在两次tcp传输过程中。另外如果包头前6个字节不是指定的标识,要向后顺延,直到找出包头。

3、思路

1)使用两个ByteBuffer对象,一个记录数据段前的10个字节,该对象仅创建一次。另一个ByteBuffer对象存储去除包头后的完整的数据段信息,该对象在每次接收新的包头时,都会根据包头的后4个字节重新创建(因为jvm的自动垃圾回收,所以这里不用担心内存溢出问题)。

2)接收完整的数据段后,如果还有多余数据则使用迭代方式处理。

4、java代码实现

1、这里只列出了核心代码,相关逻辑需要自己补全2、创建tcp服务端代码
try (ServerSocket ss = new ServerSocket(port)) {while (true) {Socket socket = ss.accept();new SocketHandler(socket, eqpmtId, port, save).start();}
} catch (Exception e) {log.error("TCP服务端创建异常,端口为{},异常为\n", this.port, e);
}3、tcp服务端详细处理代码
@Slf4j
class SocketHandler extends Thread {private Socket socket;private String eqpmtId;private Integer port;private boolean save;public SocketHandler(Socket socket, String eqpmtId, Integer port, boolean save) {this.socket = socket;this.eqpmtId = eqpmtId;this.port = port;this.save = save;}@Overridepublic void run() {log.info("与{},{}建立消息socket通信", eqpmtId, port);try (InputStream inputStream = socket.getInputStream();FileOutputStream os = new FileOutputStream(new File("D:\\tmp-data\\" + System.currentTimeMillis() + ".h264"));) {byte[] buffer = new byte[64 * 1024];int len = 0;ByteBuffer dataBuffer = null;ByteBuffer headBuffer = ByteBuffer.allocate(10);while (socket.isConnected() && !socket.isClosed()) {if ((len = inputStream.read(buffer)) != -1) {log.info("收到数据包len={}", len);try {dataBuffer = getDataBuffer(buffer, 0, len, headBuffer, dataBuffer);} catch (Exception e) {log.error("接收数据异常,重新开始接收...\n",e);headBuffer.clear();dataBuffer.clear();}} else {log.info("没有数据,休眠1秒,否则cpu会飙升");Thread.sleep(1000);}}} catch (Exception e) {log.error("socket传输异常,异常为\n", this.port, e);}log.info("关闭与},{}消息socket通信", eqpmtId, port);}private ByteBuffer getDataBuffer(byte[] buffer, int start, int end, ByteBuffer headBuffer, ByteBuffer dataBuffer) {int offset = start;int tmpLen = 0;//先找到包头if (headBuffer.position() < headBuffer.capacity()) {//当前数组长小于包头长度有,整个数组放入头缓存后返回int len = end - offset;if (len < headBuffer.capacity() - headBuffer.position()) {headBuffer.put(buffer, offset, len);return dataBuffer;}tmpLen = headBuffer.capacity() - headBuffer.position();headBuffer.put(buffer, offset, headBuffer.capacity() - headBuffer.position());offset = offset + tmpLen;//包头缓存填充满了,判断包头是否正确if (!isHead(headBuffer.array())) {//包头不正确,则不断向后移位直到找到包头log.info("包头有问题,向后移动一位继续校验");int headLastIndex = headBuffer.capacity() - 1;for (; offset < end; offset++) {for (int i = 0; i < headLastIndex; i++) headBuffer.put(i, headBuffer.get(i + 1));headBuffer.put(headLastIndex, buffer[offset]);if (isHead(headBuffer.array())) break;}//移位结束确认是找到了包头还是当前数组已经遍历完if (!isHead(headBuffer.array())) {headBuffer.position(headLastIndex);return dataBuffer;}}//包头正确后,解析获取数据包有多长,并创建对应的缓存对象int dataLen = dataLen(headBuffer.array());log.info("包头设定长度为{}", dataLen);dataBuffer = ByteBuffer.allocate(dataLen);}if (offset == end) return dataBuffer;//如果可以填充满数据缓存对象,则发送数据包,并清理缓存if (end - offset >= dataBuffer.capacity() - dataBuffer.position()) {tmpLen = dataBuffer.capacity() - dataBuffer.position();dataBuffer.put(buffer, offset, dataBuffer.capacity() - dataBuffer.position());offset = offset + tmpLen;/** 收到完整数据包,进行处理,注意这里的函数要替换成自己的处理逻辑 **/sendData(dataBuffer, null);dataBuffer.clear();headBuffer.clear();if (offset == end) return dataBuffer;//迭代处理剩下的数据return getDataBuffer(buffer, offset, end, headBuffer, dataBuffer);}//如果不能填充慢数据缓存对象,则整个数据放入后返回dataBuffer.put(buffer, offset, end - offset);return dataBuffer;}//判断是否为包头public boolean isHead(byte[] buffer) {if (buffer == null || buffer.length < 10) return false;int b1 = buffer[0];int b2 = buffer[1];int b3 = buffer[2];int b4 = buffer[3];int b5 = buffer[4];int b6 = buffer[5];String s = "" + b1 + b2 + b3 + b4 + b5 + b6;if ("001001".equals(s)) return true;return false;}//判断数据包的长度(ByteUtil用的hutool工具包里的类,也可以自己实现)public int dataLen(byte[] buffer) {return ByteUtil.bytesToInt(new byte[]{buffer[6], buffer[7], buffer[8], buffer[9]});}}

http://www.hkea.cn/news/387802/

相关文章:

  • wordpress添加日历首页优化公司
  • 日本可以自己做网站吗查询网站服务器
  • 做网站维护的人叫啥友情链接交换工具
  • 云南网站定制真正永久免费的建站系统有哪些
  • 温州做网站技术员沧州做网络推广的平台
  • wordpress media上海排名优化seobwyseo
  • 深圳网站建设科技有限公司注册一个网站
  • 网站设计改版seo关键词优化推广价格
  • 做网站什么主题比较好上海网站seo诊断
  • 设计苹果手机的网站病毒什么时候才能消失
  • 国外做化工产品的网站自媒体发布平台
  • 怎么做资源类网站百度搜索热度排名
  • 大片网站建设seo关键词排名优化评价
  • 网络营销推广课程培训苏州seo门户网
  • 做盗版影视网站如何给公司网站做推广
  • 做网站付费流程郑州seo技术
  • 云南网站开发有哪些实用的网络推广方法
  • 央视新闻最新消息今天什么叫seo
  • 网站建设的意义徐州百度推广
  • 建设网站建设的目标百度云盘资源
  • 个体工商户是否能够做网站在线生成个人网站源码
  • 临沂高端网站建设厦门网站推广费用
  • 网站模版友链交易交易平台
  • 武汉做网站找谁百度导航是哪个国家的
  • wordpress互动游戏黄石seo诊断
  • 网页设计作品下载志鸿优化设计
  • 宾馆网站制作seminar是什么意思
  • 网站建设的进度表爱站查询工具
  • 深圳聘请做网站人员长春刚刚最新消息今天
  • 汽配人网做网站沈阳网站seo公司