看第一个解析API:
private void ParseData(byte[] data) { var paramBytes = SplitBuffer(data); RawParam = _encoding.GetString(paramBytes); ParseParamString(RawParam); }
再看如何分隔数据包:
private byte[] SplitBuffer(byte[] data) { int paramIndex = MathUtils.IndexOf(data, EnterChar); //以“\r\n\r\n”为分隔符 byte[] paramBytes; if (paramIndex >= 0) //如果有双换行符 { paramBytes = new byte[paramIndex]; Buffer.BlockCopy(data, 0, paramBytes, 0, paramBytes.Length); //将双换行符之前的数据复制出来 InputStream = new byte[data.Length - paramIndex - EnterChar.Length]; Buffer.BlockCopy(data, paramIndex + EnterChar.Length, InputStream, 0, InputStream.Length); //将剩下的数据复制到 InputStream } else { paramBytes = data; } return paramBytes; }
看 Scut 的官方文档,对此也说的很清楚:第一部分是字符串的格式流(命名为Get Params),第二部分是扩展数据流(可选),支持上传些文件流或图片流等,与第一部分之间需要以两个换行(\r\n\r\n)符分隔。
重点则是对第一部分的格式分析:
protected virtual void ParseParamString(string paramString) { string str = paramString; int index = paramString.IndexOf(PrefixParamChar, StringComparison.OrdinalIgnoreCase); //找到协议前缀的位置 if (index != -1) { if (paramString.StartsWith(PrefixRouteChar, StringComparison.OrdinalIgnoreCase)) { //ex: "route:xxx?d=" RouteName = paramString.Substring(PrefixRouteChar.Length, index - PrefixRouteChar.Length); } str = paramString.Substring(index + PrefixParamChar.Length); //从协议前缀位置开始截断 str = HttpUtility.UrlDecode(str) ?? ""; } if (!str.Contains("=")) { TraceLog.ReleaseWriteDebug("Parse request error:{0}", paramString); return; } var nvc = HttpUtility.ParseQueryString(str); //根据 xx=xx&xx=xx 的规则取出数据 foreach (var key in nvc.AllKeys) { if (string.IsNullOrEmpty(key)) continue; var val = nvc[key]; if (PrefixRouteChar.StartsWith(key, StringComparison.OrdinalIgnoreCase)) { RouteName = val; continue; } this[key] = val; } }
总结:
1. SplitBuffer 主要是做第一部分与第二部分的分离;
2. 第一部分:可知的规则是 ?d=Key1=Value1&Key2=Value2... 并且要执行一次 Url 编码;
时间: 2024-10-12 02:03:33