精华内容
下载资源
问答
  • 12位)、帧起始符68、控制码(一个字节)、数据标识(4个字节)、有效数据长度(一个字节)、有效数据、帧内校验CS(一个字节)、帧结束符16、帧校验码CRC(两个字节),而RS485数据帧把载波帧的前面的标识7E AA和

    电力载波通信数据帧的每一个结构码应该都有它的特殊功能,就象从站上报数据给主站,上行码为00,其实这里00是兼容了RS485帧和载波帧两种格式,载波数据帧是以前导码FE FE FE FE开头,然后是7E AA,然后是后面的数据长度、上/下行标识码(80/00)、帧起始符68、地址(6个字节,12位)、帧起始符68、控制码(一个字节)、数据标识(4个字节)、有效数据长度(一个字节)、有效数据、帧内校验CS(一个字节)、帧结束符16、帧校验码CRC(两个字节),而RS485数据帧是把载波帧的前面的标识7E AA和帧长度、帧校验CRC去掉,这样,如果主站收到数据帧时,就是以辨别出是载波帧还是RS485帧,这两种帧有两个共同的地方就是,帧起始符包含两个68,第二个就是CS,如果是同一包数据分别以RS485格式和载波格式发送出来,它们的CS是相等的,这样,在主站接收到数据时,载波数据帧就是多一些容错性,如果主站收到数据后,先判断是不是包含7E,如果刚好传输过程中7E发生了错误,变成其它的数据,还可以再以RS485格式来解析,当分析出帧起始符68,然后判断CS是否对,虽然两种格式的数据帧不一样,但它们的CS计算是一样的,载波帧是从第一个起始符68开始到后面有效数据之间的数据来计算的,而485帧是也是从第一个起始符68开始到后面有效数据之间的数据来计算的,则它们计算出的CS是相等的,这样,当载波帧在传输中如果有一些字节错了,还可以当485帧来解析,多了一道传输安全性。

    展开全文
  • 通信协议中的转义

    2017-06-21 20:23:00
    由于通信的接收方才知道什么时候通信的開始和结束。那么如果头(通信的開始)为0x02(也能够其它),尾为0x03(也能够其它),粗略的一看没有问题的,可是试想如果在头和尾的中间数据出现0x02或者0x...
    通信协议中的转义符
    作用:在通信协议中用在协议中使得通信的内容更加安全可靠。
    举例说明:如果如今须要定制一个通信协议。须要的最主要的就是一个帧头和帧尾的标志。由于通信的接收方才知道什么时候是通信的開始和结束。那么如果帧头(通信的開始)为0x02(也能够是其它),帧尾为0x03(也能够是其它),粗略的一看是没有问题的,可是试想如果在帧头和帧尾的中间数据出现0x02或者0x03的时候整个通信过程将会被破坏掉,由于本来一帧数据还没有传输完毕,接收方误以为接收到帧头或者帧尾就会又一次開始接收数据(导致前面已经接收的数据丢失)或者结束接收数据(导致后面的数据无法接收)。理论上来讲帧头和帧尾不管定义为什么字符都会可能出在通信数据中,由于我们不应该对用户传输的通信数据做出不论什么的如果。那么怎样解决问题呢?转义字符就是用来解决问题的。先看以下的这张图片:

    这张图片中再增加了一个字符即0x1B。这个字符被定义为转义字符(也能够设置为别的),增加这个字符后的传输过程变为,0x02+用户数据+0x03。可是在用户数据中假设出现0x02即被替换为0x1B+0xE7,假设出现0x03即被替换为0x1B+0xE8。这样用户数据中就绝不会再出现0x02和0x03。可是万一用户要传输的数据就是0x1B+0xE7呢?这也没有关系,由于假设用户要传输的0x1B也会被转义为0x1B+0x00,所以假设用户真的须要传输0x1B+0xE7的话也被0x1B+0x00+0xE7所替代,也不会造成干扰。

    这样做的结果是在接收端假设接收到转义字符,就必须要推断下一个字符是否为特定的三个值,假设是特定的三个值就须要做特殊处理,这就是转义字符解决通信中防止通信错误的原理。

    展开全文
  • 帧开始符:SOH,帧结束符:EOT 透明传输 很多同学初学计算机网络时可能对透明传输不是很理解。其实,透明传输就是指无论是什么报文都可以进行传输,而相对的非透明传输就是指某些特殊字符不能传输。假设帧在传输...

    在这里插入图片描述

    重点知识总结:

    1.数据链路层的三个基本问题

    • 封装成帧
      封装成帧(framing)就是在一段数据的前后分别添加首部和尾部,然后就构成了一个帧。确定帧的界限。首部和尾部的一个重要作用就是进行帧定界。 帧开始符:SOH,帧结束符:EOT
      在这里插入图片描述
    • 透明传输
      很多同学初学计算机网络时可能对透明传输不是很理解。其实,透明传输就是指无论是什么报文都可以进行传输,而相对的非透明传输就是指某些特殊字符不能传输。假设帧在传输过程中传输数据部分包含EOT,那么可以采用字节填充法解决此类问题。即在EOT前加上转义字符,在接收端再删去转义字符。这就是透明传输需要解决的问题。
      透明传输即发送什么我就接受什么,中间没有出现差错。
      差错控制
      循环冗余检验CRC

    2.PPP协议

    • PPP协议的帧格式
      在这里插入图片描述

    标志字段 F = 0x7E (符号“0x”表示后面的字符是用十六进制表示。十六进制的 7E 的二进制表示是 01111110)。
    地址字段 A 只置为 0xFF。地址字段实际上并不起作用。
    控制字段 C 通常置为 0x03。
    PPP 是面向字节的,所有的 PPP 帧的长度都是整数字节。

    • 零比特填充
      PPP 协议采用零比特填充方法来实现透明传输

    • 不使用序号和确认机制

    • PPP协议的工作状态
      在这里插入图片描述

    3.广播信道

    • 局域网拓扑:星型、总线型、树型、环形
    • 局域网特点
      局域网最主要的特点是:网络为一个单位所拥有,且地理范围和站点数目均有限。
      局域网具有如下的一些主要优点:
      具有广播功能,从一个站点可很方便地访问全网。局域网上的主机可共享连接在局域网上的各种硬件和软件资源。
      便于系统的扩展和逐渐地演变,各设备的位置可灵活调整和改变。
      提高了系统的可靠性、可用性和生存性。

    4.以太网

    以太网与局域网区别:
    以太网是一种局域网,但是因为现在大部分的局域网均为以太网,因此一般提及局域网都会默认为以太网。以太网为总线型,而局域网有星型、树型等。
    以太网通常采用CSMA/CD协议(即:带冲突检测的载波监听多路访问协议),而局域网的使用协议多样,包括TCP/IP协议、IPX/SPX协议、NetBEUI协议等。

    • 重要特性
      使用 CSMA/CD 协议的以太网不能进行全双工通信而只能进行双向交替通信(半双工通信)。
      每个站在发送数据之后的一小段时间内,存在着遭遇碰撞的可能性。
      这种发送的不确定性使整个以太网的平均通信量远小于以太网的最高数据率。
    • 集线器、网桥、交换机、路由器
      集线器(HUB)是工作在物理层用以扩展以太网的设备。它把一个端口接收的所有信号向所有端口分发出去(广播)。所以集线器将几个冲突域连接在一起形成一个更大的冲突域。
      网桥(Bridge)是工作在数据链路层用以扩展以太网的设备。它根据 MAC 帧的目的地址对收到的帧进行转发,具有过滤帧的功能。当网桥收到一个帧时,并不是向所有的接口转发此帧,而是先检查此帧的目的 MAC 地址,然后再确定将该帧转发到哪一个接口。因此网桥将各个冲突域连接起来。
      交换机(Switch)是一个多接口的网桥。交换机能同时连通许多对的接口,使每一对相互通信的主机都能像独占通信媒体那样,进行无碰撞地传输数据。交换机的使用使得VLAN(虚拟局域网)的创建成为可能。
      路由器(Router)处于网络层。主要工作就是为经过路由器的每个数据帧寻找一条最佳传输路径,并将该数据有效地传送到目的站点。

    5.虚拟局域网VLAN
    虚拟局域网 VLAN 是由一些局域网网段构成的与物理位置无关的逻辑组。

    • 这些网段具有某些共同的需求
    • 每一个 VLAN 的帧都有一个明确的标识符,指明发送这个帧的工作站是属于哪一个 VLAN。

    虚拟局域网其实只是局域网给用户提供的一种服务,而并不是一种新型局域网。

    在这里插入图片描述
    跨交换机的VLAN使用干道链路连接
    在这里插入图片描述
    企业局域网设计
    企业局域网设计
    如何查看MAC地址(唯一,但是可以修改)
    一般MAC地址由生产厂家直接烧入网卡。是惟一的。
    如果电脑上设置有随机硬件地址分配,则连接不同的WIFI会有不同的MAC地址。

    在这里插入图片描述

    展开全文
  • 2.6 结束符16H:表示信息的结束。 传输次序:数据域数据均应先传送低位字节,后传送高位字节。 2.8 差错控制:校验为纵向信息校验和,接收方无论检测到纵向信息校验和出错,放弃该信息, 不予响应。在...
  • 您用TCP Socket协议也就罢了,可是您还通信协议只有开始符,没有结束符是怎么回事。 您还用不可见字符,二进制的,不便于调试。请问这都什么年代了,您的MCU(单片机)性能有那么弱吗? 来看一下通信协议: 通信...

    spring-boot 建socket服务器,处理物联网设备的粘包分包

    首先dis一下某些物联网设备的通信协议。

    您用TCP Socket协议也就罢了,可是您还通信协议只有开始符,没有结束符是怎么回事。
    您还用不可见字符,二进制的,不便于调试。请问这都什么年代了,您的MCU(单片机)性能有那么弱吗?
    来看一下通信协议:

    通信帧格式:
    	名称	长度	说明
            帧头
    
    	 开始标识         	2Byte	0xEF3A (高字节在前)
    	数据长度	               2 Byte	长度是指信道、协议版本、命令、内容、CRC 五者的字节之和。(高字节在前)
    	信道	                         1 Byte	                           0x01 服务发出	4G/2G
    			                                                         0x02 设备发出	
    	协议版本	               1 Byte	当前版本 0x01
    
    帧数据	
            命令	                           1 Byte	
    	数据	                          N Byte	
         
              校验	CRC16	2 Byte	将开始标识、长度、信道、协议版本、命令和内容这六部分
    内容的所有字节进行 CRC 计算(高字节在前)
    

    别欺负我不懂MCU, 我以前也是干硬件出身,PCB也画过,MCU软件也写过,机器也量产过。
    以上叨B叨那么多,硬件改不了,还是要对接啊。以下开始:

    1. 来人,上netty

    image.png

    其它的也就不説了,各种文章太多了,
    来看看核心部分:

    public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
        @Override
        protected void initChannel(SocketChannel socketChannel) throws Exception {
    
            //这是用最简单的分割符来分割
            //ByteBuf delimiter = Unpooled.copiedBuffer("#".getBytes());
    
            //添加编解码
            //socketChannel.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
            //socketChannel.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
    
            //前置,处理了普通分隔符作为报文结束符的分包和粘包问题,不过不适合此例子
            //socketChannel.pipeline().addLast(new MyDelimiterBasedFrameDecoder(1024, delimiter));
    
            socketChannel.pipeline().addLast("decoder", new MyBinDecoder(CharsetUtil.UTF_8));
            socketChannel.pipeline().addLast("encoder", new MyBinEncoder(CharsetUtil.UTF_8));
            socketChannel.pipeline().addLast(new NettyServerHandler());
        }
    }
    
    1. 怎么写具体的协议解析

    然后,就是我们定义的MyBinDecoder 最重要:

    public class MyBinDecoder extends MessageToMessageDecoder<ByteBuf> {
        private final Charset charset;
    
        //上次的半包. 用于处理分包情况
        private String lastHalfPacket = "";
    
        public MyBinDecoder() {
            this(Charset.defaultCharset());
        }
    
        public MyBinDecoder(Charset charset) {
            if (charset == null) {
                throw new NullPointerException("charset");
            } else {
                this.charset = charset;
            }
        }
    
        protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
            List<String> cmdList = parseCmdList(msg);
    
            if(cmdList!=null && !cmdList.isEmpty()) {
                log.info("添加list");
                out.addAll(cmdList);
            }else{
                System.out.println("暂未发现指令");
            }
    
        }
    
        byte[] starter = new byte[]{ (byte)0xEF, (byte)0x3A};
        final int CMD_HEADER_LENGTH = 6;
    
        private List<String> parseCmdList(ByteBuf originBuf){
            ByteBuf buf = Unpooled.buffer(1024);
            buf.writeBytes(ByteBufUtil.decodeHexDump(lastHalfPacket));
            buf.writeBytes(originBuf);
            List<String> result = new ArrayList<>();
    
            log.info("开始遍历 buf readableBytes=" + buf.readableBytes());
    
            try {
                while(buf.readableBytes() >= CMD_HEADER_LENGTH) {
                    byte[] bStart = new byte[2];
                    //String hex = ByteBufUtil.hexDump(b);
                    buf.getBytes(buf.readerIndex(), bStart);
                    log.info("读starter:" + ByteBufUtil.hexDump(bStart));
                    if (compareBytes(bStart, starter)) {
                        log.info("找到了start");
                        //判断这次长度够不够读,如果不够读直接退出
                        //如果够读,读进来,插进cmd list
                            byte[] bHeader = new byte[CMD_HEADER_LENGTH];
                            //buf.markReaderIndex();
                            //buf.readBytes(bHeader);
                            buf.getBytes(buf.readerIndex(), bHeader);
                            int dataLength = bHeader[2] * 256 + bHeader[3];
                            //buf.resetReaderIndex();
                            int THEORYLENGTH = 4 + dataLength;
                            log.info("命令总长度: " + THEORYLENGTH);
    
                            if(buf.readableBytes() >= THEORYLENGTH) {
                                log.info("正在读全长");
                                byte[] bCmdFrame = new byte[THEORYLENGTH];
                                buf.readBytes(bCmdFrame);
                                //readerIndex += THEORYLENGTH;
                                String hexCmd = ByteBufUtil.hexDump(bCmdFrame);
                                log.info("找到一个指令啦:" + hexCmd);
                                result.add(hexCmd);
                                log.info("读缓冲区还有:" + buf.readableBytes());
                                continue;
                            }else{
                                log.info("命令总长未达预期,下次再读");
                                int halfPacketNum = buf.readableBytes();
                                byte[] bHalfPacket = new byte[halfPacketNum];
                                buf.readBytes(bHalfPacket);
                                if(halfPacketNum>=1) {
                                    String halfPacketStr = ByteBufUtil.hexDump(bHalfPacket);
                                    log.info("剩下半包"+halfPacketStr);
                                    lastHalfPacket = halfPacketStr==null? "": halfPacketStr;
                                }
                                return result;
                            }
    
                    } else {
                        //读指针向后移动一个
                        log.info("没找到starter,读指针向后移动一个");
                        buf.readBytes(1);
                        continue;
                    }
                }
    
                int halfPacketNum = buf.readableBytes();
                if(halfPacketNum > 0) {
                    log.info("HEADER命令头未达预期,下次再读");
                    byte[] bHalfPacket = new byte[halfPacketNum];
                    buf.readBytes(bHalfPacket);
                    String halfPacketStr = ByteBufUtil.hexDump(bHalfPacket);
                    log.info("剩下半包"+halfPacketStr);
                    lastHalfPacket = halfPacketStr==null? "": halfPacketStr;
                }else{
                    log.info("余下字节恰好为0,本轮读完了");
                }
            }catch (Exception e){
                e.printStackTrace();
                log.warn(e.toString());
                return result;
            }
    
            return result;
        }
    
        private boolean compareBytes(byte[] b1, byte[] b2){
            if(b1==null && b2==null){
                return true;
            }
            if( (b1==null && b2!=null) || (b1!=null && b2==null)){
                return false;
            }
            if(b1.length != b2.length){
                return false;
            }
            for(int i = 0; i<b1.length; i++){
                if( b1[i]!=b2[i]){
                    return false;
                }
            }
            return true;
        }
    
    }
    
    1. 后记
      这是个半成品,只是打印出来了十六进制转成了HEX STRING的结果。后续对指令的处理,自己再加吧。

    伸手党可去CSDN下载源码
    https://download.csdn.net/download/stephenzhu/16593276

    展开全文
  • 一般通信不管什么物理方式,如RS232、485、CAN、网口等,都将数据首先定义成意义明确的,每数据大体上都包含头、命令字、长度域、有效数据域、校验域、结束符等这几个部分,收发双方都遵循一个固定的...
  • 数据链路层所包含的主要协议:点对点协议PPP、CSMA/CD协议、地址解析协议ARP、逆地址解析协议RARP ... 封装成:PPP协议必须规定特殊的字符作为定界(即标志一个的开始和结束的字符),...
  • 举例说明:假设现在需要定制一个通信协议,需要的最基本的就是一个头和尾的标志,因为通信的接收方才知道什么时候通信的开始和结束。 那么假设头(通信的开始)为0x02(也可以其他),尾为0x03(也可以...
  • 一、数据链路层总体概述 ...接收时,遇见转义字符一律剔除,直到遇见结束符为止。 3. 零比特填充法 为了防止数据部分有与边界 011111100111111001111110 相同的比特组合,一旦数据部分出现1111111111
  • 转载---点击打开链接原子哥的开发板例程《实验4 串口实验》中,利用特殊数据(回车)来确定结束的,所以必须在发送数据后再发送一个回车(比如说有的项目中一数据中中间要是有回车就没法用了),其实STM32...
  • Python核心编程第二版(中文)

    热门讨论 2015-04-23 16:40:13
    6.8.4 Codec是什么 6.8.5 编码解码 6.8.6 把Unicode应用到实际应用中 6.8.7 从现实中得来的教训 6.8.8 Python的Unicode支持 6.9 相关模块 6.10 字符串关键点总结 6.11 列表 6.12 操作 6.12.1 标准类型...
  • 深入理解Python中文版高清PDF

    热门讨论 2012-09-04 19:37:04
     6.8.4 Codec是什么   6.8.5 编码解码   6.8.6 把Unicode应用到实际应用中   6.8.7 从现实中得来的教训   6.8.8 Python的Unicode支持   6.9 相关模块   6.10 字符串关键点总结  6.11 ...
  •  6.8.4 codec是什么   6.8.5 编码解码   6.8.6 把unicode应用到实际应用中   6.8.7 从现实中得来的教训   6.8.8 python的unicode支持   6.9 相关模块   6.10 字符串关键点总结  6.11 列表  ...
  • Python核心编程(中文第二版)

    热门讨论 2009-10-02 12:08:14
     6.8.4 Codec是什么   6.8.5 编码解码   6.8.6 把Unicode应用到实际应用中   6.8.7 从现实中得来的教训   6.8.8 Python的Unicode支持   6.9 相关模块   6.10 字符串关键点总结  6.11 列表  ...
  • Python核心编程第二版(ok)

    热门讨论 2009-05-21 08:23:44
     6.8.4 Codec是什么   6.8.5 编码解码   6.8.6 把Unicode应用到实际应用中   6.8.7 从现实中得来的教训   6.8.8 Python的Unicode支持   6.9 相关模块   6.10 字符串关键点总结  6.11 列表  ...
  •  6.8.4 codec是什么   6.8.5 编码解码   6.8.6 把unicode应用到实际应用中   6.8.7 从现实中得来的教训   6.8.8 python的unicode支持   6.9 相关模块   6.10 字符串关键点总结  6.11 列表  ...
  • Python核心编程第二版

    热门讨论 2009-07-30 17:07:20
     6.8.4 Codec是什么   6.8.5 编码解码   6.8.6 把Unicode应用到实际应用中   6.8.7 从现实中得来的教训   6.8.8 Python的Unicode支持   6.9 相关模块   6.10 字符串关键点总结  6.11 列表  ...
  • modbus通信协议

    热门讨论 2010-08-06 15:26:22
    如果便用了偶校验,的奇偶校验位将0,便得整个“1”的个数仍4个。如果便用了奇校验,的奇偶校验位将1,便得整个“1”的个数5个。 如果没有指定奇偶校验位,传输时就没有校验位,也不进行校验检测。代替...
  • 9.1.1 什么是样式单 401 9.1.2 外部样式单 404 9.1.3 嵌套样式单 406 9.1.4 内嵌样式 408 9.1.5 建立样式类 409 9.1.6 层迭样式 411 9.1.7 组织样式 412 9.1.8 理解样式规范 413 9.2 解决方案 415 9.2.1 使用外部...
  • 4.1.5 用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等。 4.1.6 JAVA8的ConcurrentHashMap为什么放弃了分段锁,有...
  • ios开发记录

    2015-08-06 23:12:11
    //此方法可以有参数,也可以没有参数,如果没有参数系统不会给你穿参数,如果有参数,只能有一个参数,无论你所指定的参数类型是什么,系统只会把tf本身给传过去 [tf addTarget:self action:@selector(down:) ...
  • 5、正确使用逻辑与&&、屏蔽&操作 第17页 【案例1.5.1】 第17页 6、注意数据类型的匹配 第18页 【案例1.6.1】 第18页 【案例1.6.2】 第18页 7、用于控制条件转移的表达式及取值范围是否书写正确 第20页 【案例1.7.1...
  • 8.1 i2c/smbus是什么161 8.2 i2c核心162 8.3 总线事务164 8.4 设备实例:eeprom164 8.4.1 初始化165 8.4.2 探测设备167 8.4.3 检查适配器的功能169 8.4.4 访问设备169 8.4.5 其他函数170 8.5 ...
  • dev 174 8.7 使用lm-sensors监控硬件 174 8.8 spi总线 174 8.9 1-wire总线 176 8.10 调试 176 8.11 查看源代码 176 第9章 pcmcia和cf 179 9.1 pcmcia/cf是什么 179 9.2 linux-pcmcia子系统 181 9.3 主机...
  • # EndEpochs: 结束训练的条件之样本训练轮数 Epoch 到达该条件时结束任务并编译模型。 # BatchSize: 批次大小,每一步用于训练的样本数量,不宜过大或过小,建议64。 # ValidationBatchSize: 验证集批次大小,每个...
  • 这里的IDE设备包括了IDE硬盘和IDE光驱,第一、第二组设备指主板上的第一、第二根IDE数据线,一般来说靠近芯片的第一组IDE设备,而主设备、从设备指在一条IDE数据线上接的两个设备,大家知道每根数据线上可以接...

空空如也

空空如也

1 2
收藏数 33
精华内容 13
关键字:

帧结束符是什么