您的位置:首页 > 理论基础 > 计算机网络

类的序列化与网络通讯

2014-03-23 14:41 344 查看


转自: http://www.cnblogs.com/licongjie/archive/2006/10/27/542024.htmlSocket


网络编程学习笔记(5):发送和接收实体类数据

在前面讲述的篇幅中,发送的都是文本信息,我们只要通过Encoding中的几个方法把文本转化成二进制数组就可以利用Socket来传输了,这对于一些基本的信息传输能够得到满足,但对于一些复杂的消息交流,则有些“吃力”。我们有时候会把一些信息封闭在一个类中,如果Socket能够传送类对象,那么一些复杂的问题能够通过面向对象来解决了,即方便又安全。大家都知道,要想在网络上传输信息,必须要经过序列化才行,所以在传送类对象时,首选必须对该类对象进行序列化,才能够在网络上进行传输。

序列化类对象有三种序列化方法:

1、Xml序列化

2、Binary序列化

3、Soap序列化

这几种序列化方法,运用方法相类似,只不过用到的类不一样。在这里也不一一讲述了,有兴趣的朋友可以到网上搜一搜,相信会有不少的收获。这里主要讲一下利用Soap序列化来传送消息。

1、首先我们先来建立一个实体类,用来做消息的载体



1

using System;

2

using System.Collections.Generic;

3

using System.Text;

4


5

namespace sbwConsole

6

{

7

[Serializable]

8

public class SocketData

9

{

10

private OperateType _operateType;

11

private OperateInfo _operateInfo;

12

private string _connString;

13

private string _clientIP;

14

private string _serverIP;

15


16

/// <summary>

17

/// 指令传输数据

18

/// </summary>

19

/// <param name="operateType">指令类型</param>

20

/// <param name="operateInfo">指令信息</param>

21

/// <param name="connString">ASP数据库连接字符串</param>

22

/// <param name="clientIP">子服务器IP</param>

23

/// <param name="serverIP">ASP服务器IP</param>

24

public SocketData(OperateType operateType, OperateInfo operateInfo,

25

string connString, string clientIP, string serverIP)

26

{

27

_operateType = operateType;

28

_operateInfo = operateInfo;

29

_connString = connString;

30

_clientIP = clientIP;

31

_serverIP = serverIP;

32

}

33


34

/// <summary>

35

/// 指令类型

36

/// </summary>

37

public OperateType OperateType

38

{

39

get { return _operateType; }

40

set { _operateType = value; }

41

}

42

/// <summary>

43

/// 指令信息

44

/// </summary>

45

public OperateInfo OperateInfo

46

{

47

get { return _operateInfo; }

48

set { _operateInfo = value; }

49

}

50

/// <summary>

51

/// ASP数据库连接字符串

52

/// </summary>

53

public string ConnString

54

{

55

get { return _connString; }

56

set { _connString = value; }

57

}

58

/// <summary>

59

/// 子服务器IP

60

/// </summary>

61

public string ClientIP

62

{

63

get { return _clientIP; }

64

set { _clientIP = value; }

65

}

66

/// <summary>

67

/// ASP服务器IP

68

/// </summary>

69

public string ServerIP

70

{

71

get { return _serverIP; }

72

set { _serverIP = value; }

73

}

74

}

75


76

/// <summary>

77

/// 指令类型

78

/// </summary>

79

public enum OperateType

80

{

81

/// <summary>

82

/// 网站操作

83

/// </summary>

84

Web = 0,

85

/// <summary>

86

/// 升级

87

/// </summary>

88

Upgrade,

89

/// <summary>

90

/// 迁移

91

/// </summary>

92

Transfer

93

}

94


95

/// <summary>

96

/// 指令信息

97

/// </summary>

98

public enum OperateInfo

99

{

100

/// <summary>

101

/// 发送

102

/// </summary>

103

Send = 0,

104

/// <summary>

105

/// 出错

106

/// </summary>

107

Error,

108

/// <summary>

109

/// 成功

110

/// </summary>

111

Success,

112

/// <summary>

113

/// 重发

114

/// </summary>

115

SendAgain

116

}

117

}

118


2、发送前先把类对象进行Soap序列化



1

public static void Send(NetworkStream ns, SocketData sd)

2

{

3

IFormatter formatter = new SoapFormatter();

4

MemoryStream mem = new MemoryStream();

5


6

formatter.Serialize(mem, sd);

7

byte[] data = mem.GetBuffer();

8

int memsize = (int)mem.Length;

9

byte[] size = BitConverter.GetBytes(memsize);

10

ns.Write(size, 0, 4);

11

ns.Write(data, 0, memsize);

12

ns.Flush();

13

mem.Close();

14

}

这里利用

IFormatter formatter = new SoapFormatter();

MemoryStream mem = new MemoryStream();
formatter.Serialize(mem, sd);

对类对象sd进行序列化。在这里还有一个细节值得一提,那就是消息边界问题的处理,这里是利用发送消息的长度方法来实现。代码如下:

1

int memsize = (int)mem.Length;

2

byte[] size = BitConverter.GetBytes(memsize);

3

ns.Write(size, 0, 4);

通过BitConverter.GetBytes()方法可以把数据类型转化为二进制数组,从而可以在网络上传送,所以在接收的时候先接收消息长度,再通过该长度来循环读取完整的消息。

3、接收消息



1

public static SocketData Receive(NetworkStream ns)

2

{

3

MemoryStream mem = new MemoryStream();

4

SocketData sd;

5

byte[] data = new byte[4];

6

int revc = ns.Read(data, 0, 4);

7

int size = BitConverter.ToInt32(data, 0);

8

int offset = 0;

9


10

if (size > 0)

11

{

12

while (size > 0)

13

{

14

data = new byte[1024];

15

revc = ns.Read(data, offset, size);

16

mem.Write(data, offset, revc);

17

offset += revc;

18

size -= revc;

19

}

20


21

IFormatter formatter = new SoapFormatter();

22

mem.Position = 0;

23

sd = (SocketData)formatter.Deserialize(mem);

24

mem.Close();

25

}

26

else

27

{

28

sd = null;

29

}

30

return sd;

31

}

通过sd = (SocketData)formatter.Deserialize(mem);还原数据为类对象,就可以对此类对象进行访问了。用Xml序列化或用二进制序列化也是类似,只不过把序列化的方法改一下就可以了,一般来说用二进制序列化得到的数据最小,占用带宽也最小,而用xml和Soap来序列化,都是序列化为Xml格式,所以数据比较大,占用带宽比较大。但用xml或Soap序列化,兼容性高,可以兼容不同系统之间的通信,而二进制不行。可以说各有利弊,可以根据实际情况来选择哪一种序列化。

该篇暂时就写到这里了,文字有点乱,请见谅。

源码下载:/Files/licongjie/SocketTest4.rar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: