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

xiaoxiao2021-02-28  53

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

1 int 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序列化,兼容性高,可以兼容不同系统之间的通信,而二进制不行。可以说各有利弊,可以根据实际情况来选择哪一种序列化。
转载请注明原文地址: https://www.6miu.com/read-72368.html

最新回复(0)