Socket网络编程学习笔记(5):发送和接收实体类数据
2017-06-08 10:41
549 查看
转载至:http://www.cnblogs.com/licongjie/archive/2006/10/27/542024.html
Socket网络编程学习笔记(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序列化,兼容性高,可以兼容不同系统之间的通信,而二进制不行。可以说各有利弊,可以根据实际情况来选择哪一种序列化。
相关文章推荐
- Socket网络编程学习笔记(5):发送和接收实体类数据
- 《疯狂Java讲义(第2版)》学习笔记:使用DatagramSocket发送接收数据
- iOS学习笔记4-GCDAsyncUdpSocket的使用(实现异步发送接收数据)
- TinyOS学习笔记8-简单发送接收数据
- TinyOS学习笔记8-简单发送接收数据
- 26 API-网络编程(网络概述,Socket通信机制,UDP协议发送和接收数据,TCP协议发送和接收数据)
- STM32学习笔记之USB数据接收和发送流程分析
- Qt5--学习笔记-TCPsocket文件发送、接收
- 黑马程序员--Java基础学习之网络编程(TCP、UDP、Socket、模拟发送和接收数据)
- 异步SOCKET编程-发送和接收数据
- 异步SOCKET编程-发送和接收数据
- 异步 SOCKET 编程 - 发送和接收数据
- Socket网络编程学习笔记(转)
- Socket网络编程学习笔记(1):常用方法介绍
- Linux下发送与接收组播数据(socket编程)
- ActionScript接收socket服务器发送来的数据
- Socket网络编程学习笔记(1):常用方法介绍
- Socket网络编程学习笔记(2):面向连接的Socket
- Socket网络编程学习笔记(2)
- 异步SOCKET编程-发送和接收数据[转]