1.场景介绍

较大的json包在tcp发送时会分成多个包,接收端比较难判断包的完整性,和是否存在包粘连的问题

json

包不完整

包存在粘连

{"id":"001","name":"jsonPick"}

{"id":"001","name":"json

Pick"}{"id":"001","name":"jsonPick"}

2.解决方案

  1. 用正则表达式来验证json格式是否完整
  2. 验证不完整时,等待并拼接下个包直到完整为止
  3. 当存在粘包时,用正则表达式的方案提取完整包
  4. 当存在多个完整包时,用正则表达式的方案提取多个完整包

下表为一个完整的json包、正则表达式和运行结果

json内容

{"id":"001","name":"jsonPick"}

正则表达式

\s*\{\s*"\w*\"\s*:\s*"\w*\"\s*,\s*"\w*\"\s*:\s*"\w*\"\s*\}\s*

运行结果

begin: 0

0 : "{\"id\":\"001\",\"name\":\"jsonPick\"}"

3.解决方案的多场景模拟

1.包不完整

json内容

{"id":"001","name":"json

正则表达式

\s*\{\s*"\w*\"\s*:\s*"\w*\"\s*,\s*"\w*\"\s*:\s*"\w*\"\s*\}\s*

运行结果

begin: -1

0 : ""

2.完整包,前粘连

json内容

e":"jsonPick"}{"id":"001","name":"jsonPick"}

正则表达式

\s*\{\s*"\w*\"\s*:\s*"\w*\"\s*,\s*"\w*\"\s*:\s*"\w*\"\s*\}\s*

运行结果

begin: 14

0 : "{\"id\":\"001\",\"name\":\"jsonPick\"}"

3.完整包,后粘连

json内容

{"id":"001","name":"jsonPick"}{"id":"001","name":

正则表达式

\s*\{\s*"\w*\"\s*:\s*"\w*\"\s*,\s*"\w*\"\s*:\s*"\w*\"\s*\}\s*

运行结果

begin: 0

0 : "{\"id\":\"001\",\"name\":\"jsonPick\"}"

4.完整包,前后粘连

json内容

e":"jsonPick"}{"id":"001","name":"jsonPick"}{"id":"001","name":

正则表达式

\s*\{\s*"\w*\"\s*:\s*"\w*\"\s*,\s*"\w*\"\s*:\s*"\w*\"\s*\}\s*

运行结果

begin: 14

0 : "{\"id\":\"001\",\"name\":\"jsonPick\"}"

5.包中包

json内容

{

    "id": "001",

    "name": "{\"id\":\"001\",\"name\":\"jsonPick\"}"

}

正则表达式

\s*\{\s*"\w*\"\s*:\s*"\w*\"\s*,\s*"\w*\"\s*:\s*"\w*\"\s*\}\s*

运行结果

begin: -1

0 : ""

限制于\w=Matches a word character (QChar::isLetterOrNumber(), QChar::isMark(), or '_').

\w无法匹配"、{、}等字符,故无法处理包中包的情况

4.总结

1.正则表达式能有效的判断包的完整性

2.正则表达式能在有粘包的前提下提取到完整的包

3.不支持包中包

附源码

/**
         * \s       表示一个\t、一个\n等
         * \s       Matches a whitespace character (QChar::isSpace()).
         * \s*      多个
         * \s+      至少一个
         * \s{2}    两个
         * \s{1,2}  一个到两个
         * \w       表示一个字母、一个数字、一个汉字等
         * \w       Matches a word character (QChar::isLetterOrNumber(), QChar::isMark(), or '_').
         * \w*      多个
         * \w+      至少一个
         * \w{2}    两个
         * \w{1,2}  一个到两个
         * ()       表示提取的位置
         */
        QString Output = R"(
                         {
                             "id": "001",
                             "name": "jsonPick"
                         }
                         )";
        QRegExp rx(R"(\s*\{\s*"\w*\"\s*:\s*"\w*\"\s*,\s*"\w*\"\s*:\s*"\w*\"\s*\}\s*)");

        qDebug() << "begin:" << rx.indexIn(Output);
        QStringList qsl = rx.capturedTexts();

        for(int i = 0; i < qsl.count(); i++)
        {
            qDebug() << i << ": " << qsl.at(i);
        }

        return 1;

运行结果

begin: 0

0 : "\n {\n \"id\": \"001\",\n \"name\": \"jsonPick\"\n }\n "