• 文本协议篇1-文本协议的设计与实现


    1. 发送缓冲区和接收缓冲区的概念

    • 缓冲区:暂存数据的内存空间
    • 发送缓冲区:数据先进入发送缓冲区,之后由操作系统发送到远端主机
    • 接收缓冲区:远端数据被操作系统接受后放入接收缓冲区 

    2. 数据粘黏问题

    • 接收端无法知道数据的发送方式。 

     

    3. 应用层协议

    • 网络程序设计中期望
      • 每次发送一条完整的消息,每次接收一条完整的消息(发送和接收都是以一条完整的消息为单位进行)
      • 即使接受缓冲区中有多条消息,消息之间有明显的界限,不会出现消息粘粘
      • 消息中增加一些额外的类型,其涵盖了数据类型和数据长度等信息
    • 什么是协议
      • 协议是通讯双方为了数据交换而建立的规则、标准或规定的集合 
        -协议对数据传输的作用
      • 通讯双方根据协议能够正确收发数据
      • 通讯双方根据协议能够正确解释数据的意义 
        -协议设计示例
      • 完整的消息包含
        • 数据头:数据类型(指明了数据区的用途,长度固定)
        • 数据长度:数据区的长度(长度固定)
        • 数据区:字符数据(变长区域)

    4. 协议设计示例

    • 数据消息至少8个字符
    • 可通过计算数据消息的总长度,能够避开数据粘粘问题

    5. 代码

    实现功能如下

    1. 将协议对象组装成一个完整的字符串类型的消息
    2. 将一个满足协议规则的字符串装配成一个协议对象
    3. 详见main函数测试

    TextMessage.pro

     1 QT -= gui
     2 
     3 CONFIG += c++11 console
     4 CONFIG -= app_bundle
     5 
     6 # The following define makes your compiler emit warnings if you use
     7 # any feature of Qt which as been marked deprecated (the exact warnings
     8 # depend on your compiler). Please consult the documentation of the
     9 # deprecated API in order to know how to port your code away from it.
    10 DEFINES += QT_DEPRECATED_WARNINGS
    11 
    12 # You can also make your code fail to compile if you use deprecated APIs.
    13 # In order to do so, uncomment the following line.
    14 # You can also select to disable deprecated APIs only up to a certain version of Qt.
    15 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
    16 
    17 SOURCES += main.cpp 
    18     textmessage.cpp
    19 
    20 HEADERS += 
    21     textmessage.h

    textmessage.h

     1 #ifndef TEXTMESSAGE_H
     2 #define TEXTMESSAGE_H
     3 
     4 #include <QObject>
     5 
     6 class TextMessage : public QObject
     7 {
     8     Q_OBJECT
     9     QString m_type;
    10     QString m_data;
    11 public:
    12     explicit TextMessage(QObject *parent = nullptr);
    13     TextMessage(QString type, QString data, QObject* parent = NULL);
    14 
    15     QString type();
    16     int length();
    17     QString data();
    18 
    19     QString serialize();
    20     bool unserialize(QString s);
    21 signals:
    22 
    23 public slots:
    24 };
    25 
    26 #endif // TEXTMESSAGE_H

    textmessage.cpp

     1 #include "textmessage.h"
     2 
     3 TextMessage::TextMessage(QObject *parent) : QObject(parent)
     4 {
     5     m_data="";
     6     m_type="";
     7 }
     8 
     9 TextMessage::TextMessage(QString type, QString data, QObject* parent):QObject(parent)
    10 {
    11     m_type=type.trimmed();
    12 
    13     m_type.resize(4,' ');
    14 
    15     m_data=data.mid(0,0xFFFF);
    16 
    17 }
    18 
    19 QString TextMessage::type()
    20 {
    21     return m_type;
    22 }
    23 
    24 int TextMessage::length()
    25 {
    26     return m_data.length();
    27 }
    28 
    29 QString TextMessage::data()
    30 {
    31     return m_data;
    32 }
    33 
    34 QString TextMessage::serialize()
    35 {
    36     QString len=QString::asprintf("%X", m_data.length());
    37 
    38     len.resize(4,' ');
    39 
    40     return m_type+len+m_data;
    41 }
    42 
    43 bool TextMessage::unserialize(QString s)
    44 {
    45     bool ret=(s.length()>=8);
    46 
    47     if(ret)
    48     {
    49         QString type=s.mid(0,4);
    50         QString len=s.mid(4,4);
    51         int length=len.toInt(&ret,16);
    52 
    53         ret=ret&&( (s.length()-8)==length);
    54 
    55         if(ret)
    56         {
    57             m_type=type;
    58             m_data=s.mid(8,length);
    59         }
    60     }
    61 
    62     return  ret;
    63 }

    main.cpp

    #include <QCoreApplication>
    #include <QDebug>
    #include "textmessage.h"
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        TextMessage tm("AB","1234567890");
        QString message=tm.serialize();
    
        qDebug()<<message;
    
        TextMessage tmt;
    
        tmt.unserialize(message);
    
        qDebug()<<tmt.type();
        qDebug()<<tmt.length();
        qDebug()<<tmt.data();
    
        return a.exec();
    }

    结果 

    6.小结

    • TCP编程发送数据时,数据先被放于发送缓冲区
    • TCP编程接受数据时,从接收缓冲区中取数据
    • TCP接收端无法知道数据的发送方式,可能产生数据的粘粘问题
    • TCP编程时可通过建立协议规则解决数据粘粘问题
  • 相关阅读:
    线程高并发
    29(套接字)就是网络编程
    28线程
    27 枚举
    26静态导入和可变参数
    25JDK新特性
    25断言 assert关键字
    24单元测试 junit
    炫酷CSS
    PHP 汉字转拼音类
  • 原文地址:https://www.cnblogs.com/zhaobinyouth/p/12250671.html
Copyright © 2020-2023  润新知