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

来源:互联网 发布:弘历筹码分布指标源码 编辑:程序博客网 时间:2024/05/22 05:05

转载至:http://www.cnblogs.com/licongjie/archive/2006/10/27/542024.html


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

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

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

      1、Xml序列化

      2、Binary序列化

      3、Soap序列化

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

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

  1using System;
  2using System.Collections.Generic;
  3using System.Text;
  4
  5namespace 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序列化


 1public 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进行序列化。在这里还有一个细节值得一提,那就是消息边界问题的处理,这里是利用发送消息的长度方法来实现。代码如下:

1int memsize = (int)mem.Length;
2            byte[] size = BitConverter.GetBytes(memsize);
3            ns.Write(size, 0, 4);

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

      3、接收消息

 1public 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序列化,兼容性高,可以兼容不同系统之间的通信,而二进制不行。可以说各有利弊,可以根据实际情况来选择哪一种序列化。
阅读全文
0 0
原创粉丝点击