在上篇《
Socket开发探秘--基类及公共类的定义
》中介绍过,所有受到的数据包,经过系统的预处理后,都会得到一个PreData的数据实体,该实体包含了协议头、协议内容和所属用户的ID。PreData是定义了一个标准的协议数据格式,包含了协议关键字、协议内容、用户标识的内容。
前面说了,我们数据是通过实体类作为载体的,我们知道,收到的Socket数据经过粗略的解析后,就是PreData类型的数据,这个是通用的数据格式,我们需要进一步处理才能转化为所能认识的数据对象(实体类对象),同样,我们发送数据的时候,内容部分肯定是按照一定协议规则串联起来的数据,那么我们就需要把实体转化为发送的数据格式。综上所述,我们通过实体类,必须实现数据的发送和读取的转换。



代码


///

<summary>


///
测试数据的实体类信息

///

</summary>



public

class
TestDataRequest
{

#region
MyRegion



///

<summary>


///
请求序列

///

</summary>



public

string
seq;

///

<summary>


///
用户帐号

///

</summary>



public

string
userid;

///

<summary>


///
用户密码

///

</summary>



public

string
psw;


#endregion



public
TestDataRequest(
string
seq,
string
userid,
string
psw)
{

this
.seq
=
seq;

this
.userid
=
userid;

this
.psw
=
psw;
}

public
TestDataRequest()
{
}


///

<summary>


///
转换Socket接收到的信息为对象信息

///

</summary>


///

<param name="data">
Socket接收到的信息
</param>



public
TestDataRequest(
string
data)
{

string
[] dataArray
=

null
;
dataArray

=
NetStringUtil.UnPack(data);

if
(dataArray
!=

null

&&
dataArray.Length
>

0
)
{
TestDataRequest newAnswerData

=

new
TestDataRequest();

int
i
=

0
;

this
.seq
=
dataArray[i
++
];

this
.userid
=
dataArray[i
++
];

this
.psw
=
dataArray[i
++
];
}
}


///

<summary>


///
转换对象为Socket发送格式的字符串

///

</summary>


///

<returns></returns>



public

override

string
ToString()
{

string
data
=

""
;
data

=

this
.seq
+

"
|
"

+

this
.userid
+

"
|
"

+

this
.psw.ToString();
data

=
NetStringUtil.PackSend(DataTypeKey.TestDataRequest, data);

return
data;
}

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

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



代码


public

class
BaseEntity
{

protected

string
HeaderKey;


public
BaseEntity()
{
}


///

<summary>


///
转换Socket接收到的信息为对象信息

///

</summary>


///

<param name="data">
Socket接收到的信息
</param>



public
BaseEntity(
string
data)
{

string
[] dataArray
=

null
;
dataArray

=
NetStringUtil.UnPack(data);

if
(dataArray
!=

null

&&
dataArray.Length
>

0
)
{

int
i
=

0
;
FieldInfo[] fieldArray

=
ReflectionUtil.GetFields(
this
);

if
(fieldArray
==

null

||
dataArray.Length
!=
fieldArray.Length)
{

throw

new
ArgumentException(
"
收到的信息和字段信息不一致
"
);
}


if
(fieldArray
!=

null
)
{

foreach
(FieldInfo info
in
fieldArray)
{

string
strValue
=
dataArray[i
++
];
ReflectionUtil.SetField(

this
, info.Name, strValue);
}
}
}
}


///

<summary>


///
转换对象为Socket发送格式的字符串

///

</summary>


///

<returns></returns>



public

override

string
ToString()
{

string
data
=

""
;
FieldInfo[] fieldArray

=
ReflectionUtil.GetFields(
this
);
StringBuilder sb

=

new
StringBuilder();

if
(fieldArray
!=

null
)
{

foreach
(FieldInfo info
in
fieldArray)
{
sb.Append(ReflectionUtil.GetField(

this
, info.Name));
sb.Append(

"
|
"
);
}
}

data

=
sb.ToString().Trim(
'
|
'
);

if
(
string
.IsNullOrEmpty(HeaderKey))
{

throw

new
ArgumentNullException(
"
DataTypeKey
"
,
"
实体类未指定协议类型
"
);
}
data

=
NetStringUtil.PackSend(HeaderKey, data);

return
data;
}
}

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



代码


///

<summary>


///
测试请求

///

</summary>



public

class
TestDataRequest : BaseEntity
{

#region
字段信息



///

<summary>


///
请求序列

///

</summary>



public

string
Seq;


///

<summary>


///
用户帐号

///

</summary>



public

string
UserId;


///

<summary>


///
用户密码

///

</summary>



public

string
Password;


///

<summary>


///
消息时间

///

</summary>



public
DateTime CreateDate
=
DateTime.Now;


#endregion



public
TestDataRequest()
{

this
.HeaderKey
=
DataTypeKey.TestDataRequest;
}


public
TestDataRequest(
string
seq,
string
userid,
string
psw)
{

this
.Seq
=
seq;

this
.UserId
=
userid;

this
.Password
=
psw;

this
.HeaderKey
=
DataTypeKey.TestDataRequest;
}


///

<summary>


///
转换Socket接收到的信息为对象信息

///

</summary>


///

<param name="data">
Socket接收到的信息
</param>



public
TestDataRequest(
string
data) :
base
(data)
{

this
.HeaderKey
=
DataTypeKey.TestDataRequest;
}
}

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



代码


private

void
TestDataHandle(PreData data)
{
TestDataRequest request

=

new
TestDataRequest(data.Content);
Log.WriteInfo(

string
.Format(
"
############{0}
"
, request.ToString()));

TestDataAnswerData answerData

=

new
TestDataAnswerData(request.Seq, request.UserId, request.Password);
ShopClientManager.This.AddSend(data.UserId, answerData.ToString(),

true
);
}

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

标签: none

添加新评论