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

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