1.场景介绍
较大的json包在tcp发送时会分成多个包,接收端比较难判断包的完整性,和是否存在包粘连的问题
json | 包不完整 | 包存在粘连 |
{"id":"001","name":"jsonPick"} | {"id":"001","name":"json | Pick"}{"id":"001","name":"jsonPick"} |
2.解决方案
- 用正则表达式来验证json格式是否完整
- 验证不完整时,等待并拼接下个包直到完整为止
- 当存在粘包时,用正则表达式的方案提取完整包
- 当存在多个完整包时,用正则表达式的方案提取多个完整包
下表为一个完整的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 " |