`
isiqi
  • 浏览: 16027315 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

Socket开发探秘--数据封包和拆包

阅读更多

我们发送数据的时候,内容部分肯定是按照一定协议规则串联起来的数据,那么我们就需要把实体转化为发送的数据格式。综上所述,我们通过实体类,必须实现数据的发送和读取的转换。


///<summary>
///测试数据的实体类信息
///</summary>
publicclassTestDataRequest
{
#regionMyRegion

///<summary>
///请求序列
///</summary>
publicstringseq;
///<summary>
///用户帐号
///</summary>
publicstringuserid;
///<summary>
///用户密码
///</summary>
publicstringpsw;

#endregion

publicTestDataRequest(stringseq,stringuserid,stringpsw)
{
this.seq=seq;
this.userid=userid;
this.psw=psw;
}
publicTestDataRequest()
{
}

///<summary>
///转换Socket接收到的信息为对象信息
///</summary>
///<paramname="data">Socket接收到的信息</param>
publicTestDataRequest(stringdata)
{
string[]dataArray=null;
dataArray
=NetStringUtil.UnPack(data);
if(dataArray!=null&&dataArray.Length>0)
{
TestDataRequestnewAnswerData
=newTestDataRequest();
inti=0;
this.seq=dataArray[i++];
this.userid=dataArray[i++];
this.psw=dataArray[i++];
}
}

///<summary>
///转换对象为Socket发送格式的字符串
///</summary>
///<returns></returns>
publicoverridestringToString()
{
stringdata="";
data
=this.seq+"|"+this.userid+"|"+this.psw.ToString();
data
=NetStringUtil.PackSend(DataTypeKey.TestDataRequest,data);
returndata;
}

以上把数据的处理放在了实体类中进行封包和拆包,是一种比较好的做法,但是由于数据的封包拆包是一个繁琐的过程,代码重复性比较多,而且也容易出错。

这里设计了一个基类,来改进这种方式的数据处理,我们把所有对数据的拆包和封包,利用反射机制,减少我们的代码量,提高代码的优雅性。


publicclassBaseEntity
{
protectedstringHeaderKey;

publicBaseEntity()
{
}

///<summary>
///转换Socket接收到的信息为对象信息
///</summary>
///<paramname="data">Socket接收到的信息</param>
publicBaseEntity(stringdata)
{
string[]dataArray=null;
dataArray
=NetStringUtil.UnPack(data);
if(dataArray!=null&&dataArray.Length>0)
{
inti=0;
FieldInfo[]fieldArray
=ReflectionUtil.GetFields(this);
if(fieldArray==null||dataArray.Length!=fieldArray.Length)
{
thrownewArgumentException("收到的信息和字段信息不一致");
}

if(fieldArray!=null)
{
foreach(FieldInfoinfoinfieldArray)
{
stringstrValue=dataArray[i++];
ReflectionUtil.SetField(
this,info.Name,strValue);
}
}
}
}

///<summary>
///转换对象为Socket发送格式的字符串
///</summary>
///<returns></returns>
publicoverridestringToString()
{
stringdata="";
FieldInfo[]fieldArray
=ReflectionUtil.GetFields(this);
StringBuildersb
=newStringBuilder();
if(fieldArray!=null)
{
foreach(FieldInfoinfoinfieldArray)
{
sb.Append(ReflectionUtil.GetField(
this,info.Name));
sb.Append(
"|");
}
}

data
=sb.ToString().Trim('|');
if(string.IsNullOrEmpty(HeaderKey))
{
thrownewArgumentNullException("DataTypeKey","实体类未指定协议类型");
}
data
=NetStringUtil.PackSend(HeaderKey,data);
returndata;
}
}

以上的是实体类的基类,它封装了数据的拆包和封包过程,只需要在子类代码中指定协议头就可以了。子类的代码如下所示。

下面的代码是收到数据包,利用实体类构造函数,解析为实体类的操作,以及构造实体类,通过ToString()方式把实体类信息转化为可以发送的数据包的操作。


privatevoidTestDataHandle(PreDatadata)
{
TestDataRequestrequest
=newTestDataRequest(data.Content);
Log.WriteInfo(
string.Format("############{0}",request.ToString()));

TestDataAnswerDataanswerData
=newTestDataAnswerData(request.Seq,request.UserId,request.Password);
ShopClientManager.This.AddSend(data.UserId,answerData.ToString(),
true);
}

我编写的测试例子中,实体类的继承图如下所示。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics