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

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

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

      1、Xml序列化

      2、Binary序列化

      3、Soap序列化

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

      1、首先我们先来建立一个实体类,用来做消息的载体
ContractedBlock.gif ExpandedBlockStart.gif 类对象
  1None.gifusing System;
  2None.gifusing System.Collections.Generic;
  3None.gifusing System.Text;
  4None.gif
  5None.gifnamespace sbwConsole
  6ExpandedBlockStart.gifContractedBlock.gifdot.gif{
  7InBlock.gif    [Serializable]
  8InBlock.gif    public class SocketData
  9ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 10InBlock.gif        private OperateType _operateType;
 11InBlock.gif        private OperateInfo _operateInfo;
 12InBlock.gif        private string _connString;
 13InBlock.gif        private string _clientIP;
 14InBlock.gif        private string _serverIP;
 15InBlock.gif
 16ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
 17InBlock.gif        /// 指令传输数据
 18InBlock.gif        /// 

 19InBlock.gif        /// 指令类型
 20InBlock.gif        /// 指令信息
 21InBlock.gif        /// ASP数据库连接字符串
 22InBlock.gif        /// 子服务器IP
 23ExpandedSubBlockEnd.gif        /// ASP服务器IP

 24InBlock.gif        public SocketData(OperateType operateType, OperateInfo operateInfo,
 25InBlock.gif                          string connString, string clientIP, string serverIP)
 26ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 27InBlock.gif            _operateType = operateType;
 28InBlock.gif            _operateInfo = operateInfo;
 29InBlock.gif            _connString = connString;
 30InBlock.gif            _clientIP = clientIP;
 31InBlock.gif            _serverIP = serverIP;
 32ExpandedSubBlockEnd.gif        }

 33InBlock.gif
 34ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
 35InBlock.gif        /// 指令类型
 36ExpandedSubBlockEnd.gif        /// 

 37InBlock.gif        public OperateType OperateType
 38ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 39ExpandedSubBlockStart.gifContractedSubBlock.gif            get dot.gifreturn _operateType; }
 40ExpandedSubBlockStart.gifContractedSubBlock.gif            set dot.gif{ _operateType = value; }
 41ExpandedSubBlockEnd.gif        }

 42ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
 43InBlock.gif        /// 指令信息
 44ExpandedSubBlockEnd.gif        /// 

 45InBlock.gif        public OperateInfo OperateInfo
 46ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 47ExpandedSubBlockStart.gifContractedSubBlock.gif            get dot.gifreturn _operateInfo; }
 48ExpandedSubBlockStart.gifContractedSubBlock.gif            set dot.gif{ _operateInfo = value; }
 49ExpandedSubBlockEnd.gif        }

 50ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
 51InBlock.gif        /// ASP数据库连接字符串
 52ExpandedSubBlockEnd.gif        /// 

 53InBlock.gif        public string ConnString
 54ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 55ExpandedSubBlockStart.gifContractedSubBlock.gif            get dot.gifreturn _connString; }
 56ExpandedSubBlockStart.gifContractedSubBlock.gif            set dot.gif{ _connString = value; }
 57ExpandedSubBlockEnd.gif        }

 58ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
 59InBlock.gif        /// 子服务器IP
 60ExpandedSubBlockEnd.gif        /// 

 61InBlock.gif        public string ClientIP
 62ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 63ExpandedSubBlockStart.gifContractedSubBlock.gif            get dot.gifreturn _clientIP; }
 64ExpandedSubBlockStart.gifContractedSubBlock.gif            set dot.gif{ _clientIP = value; }
 65ExpandedSubBlockEnd.gif        }

 66ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
 67InBlock.gif        /// ASP服务器IP
 68ExpandedSubBlockEnd.gif        /// 

 69InBlock.gif        public string ServerIP
 70ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 71ExpandedSubBlockStart.gifContractedSubBlock.gif            get dot.gifreturn _serverIP; }
 72ExpandedSubBlockStart.gifContractedSubBlock.gif            set dot.gif{ _serverIP = value; }
 73ExpandedSubBlockEnd.gif        }

 74ExpandedSubBlockEnd.gif    }

 75InBlock.gif
 76ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// 
 77InBlock.gif    /// 指令类型
 78ExpandedSubBlockEnd.gif    /// 

 79InBlock.gif    public enum OperateType
 80ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 81ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
 82InBlock.gif        /// 网站操作
 83ExpandedSubBlockEnd.gif        /// 

 84InBlock.gif        Web = 0,
 85ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
 86InBlock.gif        /// 升级
 87ExpandedSubBlockEnd.gif        /// 

 88InBlock.gif        Upgrade,
 89ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
 90InBlock.gif        /// 迁移
 91ExpandedSubBlockEnd.gif        /// 

 92InBlock.gif        Transfer
 93ExpandedSubBlockEnd.gif    }

 94InBlock.gif
 95ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// 
 96InBlock.gif    /// 指令信息
 97ExpandedSubBlockEnd.gif    /// 

 98InBlock.gif    public enum OperateInfo
 99ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
100ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
101InBlock.gif        /// 发送
102ExpandedSubBlockEnd.gif        /// 

103InBlock.gif        Send = 0,
104ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
105InBlock.gif        /// 出错
106ExpandedSubBlockEnd.gif        /// 

107InBlock.gif        Error,
108ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
109InBlock.gif        /// 成功
110ExpandedSubBlockEnd.gif        /// 

111InBlock.gif        Success,
112ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// 
113InBlock.gif        /// 重发
114ExpandedSubBlockEnd.gif        /// 

115InBlock.gif        SendAgain
116ExpandedSubBlockEnd.gif    }

117ExpandedBlockEnd.gif}

118None.gif

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

ContractedBlock.gif ExpandedBlockStart.gif 消息发送方法
 1None.gifpublic static void Send(NetworkStream ns, SocketData sd)
 2ExpandedBlockStart.gifContractedBlock.gif        dot.gif{
 3InBlock.gif            IFormatter formatter = new SoapFormatter();
 4InBlock.gif            MemoryStream mem = new MemoryStream();
 5InBlock.gif
 6InBlock.gif            formatter.Serialize(mem, sd);
 7InBlock.gif            byte[] data = mem.GetBuffer();
 8InBlock.gif            int memsize = (int)mem.Length;
 9InBlock.gif            byte[] size = BitConverter.GetBytes(memsize);
10InBlock.gif            ns.Write(size, 04);
11InBlock.gif            ns.Write(data, 0, memsize);
12InBlock.gif            ns.Flush();
13InBlock.gif            mem.Close();
14ExpandedBlockEnd.gif        }


      这里利用 
            IFormatter formatter = new SoapFormatter();
            MemoryStream mem = new MemoryStream();

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

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

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

      3、接收消息
ContractedBlock.gif ExpandedBlockStart.gif 接收消息方法
 1None.gifpublic static SocketData Receive(NetworkStream ns)
 2ExpandedBlockStart.gifContractedBlock.gif        dot.gif{
 3InBlock.gif            MemoryStream mem = new MemoryStream();
 4InBlock.gif            SocketData sd;
 5InBlock.gif            byte[] data = new byte[4];
 6InBlock.gif            int revc = ns.Read(data, 04);
 7InBlock.gif            int size = BitConverter.ToInt32(data, 0);
 8InBlock.gif            int offset = 0;
 9InBlock.gif
10InBlock.gif            if (size > 0)
11ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
12InBlock.gif                while (size > 0)
13ExpandedSubBlockStart.gifContractedSubBlock.gif                dot.gif{
14InBlock.gif                    data = new byte[1024];
15InBlock.gif                    revc = ns.Read(data, offset, size);
16InBlock.gif                    mem.Write(data, offset, revc);
17InBlock.gif                    offset += revc;
18InBlock.gif                    size -= revc;
19ExpandedSubBlockEnd.gif                }

20InBlock.gif
21InBlock.gif                IFormatter formatter = new SoapFormatter();
22InBlock.gif                mem.Position = 0;
23InBlock.gif                sd = (SocketData)formatter.Deserialize(mem);
24InBlock.gif                mem.Close();
25ExpandedSubBlockEnd.gif            }

26InBlock.gif            else
27ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
28InBlock.gif                sd = null;
29ExpandedSubBlockEnd.gif            }

30InBlock.gif            return sd;
31ExpandedBlockEnd.gif        }

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

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

源码下载: /Files/licongjie/SocketTest4.rar
      

转载于:https://www.cnblogs.com/licongjie/archive/2006/10/27/542024.html

你可能感兴趣的:(Socket网络编程学习笔记(5):发送和接收实体类数据)