WinCE資料通訊之Web Service篇

Nikey001發表於2009-06-02

      準備寫個WinCE平臺與資料庫伺服器資料通訊互動方面的專題文章,今天先整理個Web Service通訊方式。

      公司目前的硬體產品平臺是WinCE5.0,資料通訊是連線伺服器與終端的橋樑,關係著終端的資料能否準確及時高效抵達伺服器,是整個專案成敗的關鍵。原先公司有同事用VC寫過一個程式用Socket進行資料通訊,但一直問題不斷。年前我開始探索用SqlCE與SqlServer資料同步方式進行資料上傳與下載,通訊已經正常穩定。這方面的文章後續再整理。

     Web Service用於PC間通訊的文章網上有很多,但用於WinCE平臺呼叫的經驗總結並不多見。Web Service的程式編寫與配置呼叫相對來講比較簡單,Visual Studio裡直接新建一個“Asp.net web 服務應用程式”就可以建立一個web Service專案了。其中的程式碼根據實際需求編寫就行,這方面就不詳述了。

      終端裝置是通過GPRS來進行資料傳輸的,因此,資料流量是非常重要的問題,應當儘可能少的減少資料傳輸,流量可是Money,壓縮技術是關鍵。Google**,找到了一款物美價廉的東東-Ihttp://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx 所謂物美是這款程式碼支援Dot net CF平臺,所謂價廉是這款程式碼完全開源免費。

      操刀開工。。。先建一個直接返回DataSet集的Web Service服務

WinCE資料通訊之Web Service篇Code

      建立一個智慧裝置應用程式,新增Web引用,我這裡用的是靜態引用,沒有用動態引用的原因是,試過網上的動態生成WebService引用的程式碼,效率遠比靜態引用要低很多,考慮終端裝置資源的有限性,還是用的靜態引用。建立好專案後在介面上新增一個button和datagrid控制元件,新增程式碼:

WinCE資料通訊之Web Service篇
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt private webSer.Service1 ws;
        
private void FrmMain_Load(object sender, EventArgs e)
WinCE資料通訊之Web Service篇        
{
            ws 
= new DeviceApplication1.webSer.Service1();
        }

        
//webmethod直接返回dataset
        private void btnDataSet_Click(object sender, EventArgs e)
WinCE資料通訊之Web Service篇        
{
            
try
WinCE資料通訊之Web Service篇            
{
                
this.dtGrid.DataSource = null;
                DateTime dtBegin 
= DateTime.Now;
                DataSet ds 
= ws.GetDataSet();
                DateTime dtDown 
= DateTime.Now;
                
this.dtGrid.DataSource = ds.Tables[0];
                MessageBox.Show(
string.Format("下載耗時:{0},繫結資料耗時:{1},資料量:{2}"
                    dtDown 
- dtBegin, DateTime.Now - dtDown, ds.GetXml().Length));
            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                MessageBox.Show(ex.ToString());
            }

        }

      連線好終端裝置,測試點選按鈕,幾秒後DataGrid表格正確顯示資料,OK,說明WinCE已經能夠正確呼叫Web Service了。如果不能正確呼叫,檢察WebService釋出與Web引用是否正確,資料庫配置是否正確。

      接下來就是要把資料進行壓縮了,壓縮前要進行資料的序列化,序列化程式碼如下:

WinCE資料通訊之Web Service篇
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtWinCE資料通訊之Web Service篇 /// 
        
/// 序列化資料成byte[]
        
/// 
        
/// 未序列化的資料
        
/// 返回序列化後的byte[]陣列

        public static byte[] byteXmlSerializer(object o)
WinCE資料通訊之Web Service篇        
{
            
if (o == null)
WinCE資料通訊之Web Service篇            
{
                
throw new ArgumentNullException("null input");
            }

            
try
WinCE資料通訊之Web Service篇            
{
                System.Xml.Serialization.XmlSerializer ser 
= new System.Xml.Serialization.XmlSerializer(o.GetType());
                System.IO.MemoryStream mem 
= new MemoryStream();
                System.Xml.XmlTextWriter writer 
= new System.Xml.XmlTextWriter(mem, Encoding.Default);
                ser.Serialize(writer, o);
                writer.Close();
                
return mem.ToArray();
            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                
throw ex;
            }

        }

WinCE資料通訊之Web Service篇 
/// 
        
/// 反序列化資料
        
/// 
        
/// 序列化後的資料
        
/// 被序列化的資料型別
        
/// 返回反序列化後的object資料

        public static object objXmlDeserialize(byte[] input, Type type)
WinCE資料通訊之Web Service篇        
{
            
if (input == null)
WinCE資料通訊之Web Service篇            
{
                
throw new ArgumentNullException("null input");
            }

            
try
WinCE資料通訊之Web Service篇            
{
                XmlSerializer mySerializer 
= new XmlSerializer(type);
                StreamReader stmRead 
= new StreamReader(new MemoryStream(input), System.Text.Encoding.Default);
                
return mySerializer.Deserialize(stmRead);
            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                
throw ex;
            }

        }

      ICSharpCode提供了多種資料壓縮的方式,我這裡測試了四種方式:BZip,Deflate,GZip,Zip

WinCE資料通訊之Web Service篇
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt private static int buffSize = 2048;//指定壓縮塊快取的大小,一般為2048的倍數
WinCE資料通訊之Web Service篇
  /// 
        
/// BZIP2壓縮資料
        
/// 
        
/// 原始未壓縮資料
        
/// 壓縮後的byte[]資料

       public static byte[] BZipCompress(byte[] input)
WinCE資料通訊之Web Service篇        
{
            
if (input == null)
WinCE資料通訊之Web Service篇            
{
                
throw new ArgumentNullException("null input");
            }

            
try
WinCE資料通訊之Web Service篇            
{
                
//int buffSize = 2048;//指定壓縮塊的大小,一般為2048的倍數
                using (MemoryStream outmsStrm = new MemoryStream())
WinCE資料通訊之Web Service篇                
{
                    
using (MemoryStream inmsStrm = new MemoryStream(input))
WinCE資料通訊之Web Service篇                    
{
                        BZip2.Compress(inmsStrm, outmsStrm, buffSize);
                    }

                    
return outmsStrm.ToArray();
                }

            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                
throw ex;
            }

        }

WinCE資料通訊之Web Service篇        
/// 
        
/// 解壓縮BZIP2資料
        
/// 
        
/// 被BZIP2壓縮過的byte[]資料
        
/// 解壓後的byte[]資料

        public static byte[] BZipDeCompress(byte[] input)
WinCE資料通訊之Web Service篇        
{
            
if (input == null)
WinCE資料通訊之Web Service篇            
{
                
throw new ArgumentNullException("null input");
            }

            
try
WinCE資料通訊之Web Service篇            
{
                
using (MemoryStream outmsStrm = new MemoryStream())
WinCE資料通訊之Web Service篇                
{
                    
using (MemoryStream inmsStrm = new MemoryStream(input))
WinCE資料通訊之Web Service篇                    
{
                        BZip2.Decompress(inmsStrm, outmsStrm);
                    }

                    
return outmsStrm.ToArray();
                }

            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                
throw (ex);
            }

        }

WinCE資料通訊之Web Service篇       
/// 
        
/// 壓縮Deflater資料
       
/// 
       
/// 待壓縮byte[]資料
       
/// 返回壓縮後的byte[]

       public static byte[] DeflaterCompress(byte[] input)
WinCE資料通訊之Web Service篇       
{
           
if (input == null)
WinCE資料通訊之Web Service篇           
{
               
throw new ArgumentNullException("null input");
           }

           
try
WinCE資料通訊之Web Service篇           
{
               Deflater mDeflater 
= new Deflater(Deflater.BEST_COMPRESSION);
               
//int buffSize = 2048;//131072 buff size
               using (MemoryStream outmsStrm = new MemoryStream())
WinCE資料通訊之Web Service篇               
{
                   
using (DeflaterOutputStream mStream = new DeflaterOutputStream(outmsStrm, mDeflater, buffSize))
WinCE資料通訊之Web Service篇                   
{
                       mStream.Write(input, 
0, input.Length);
                   }

                   
return outmsStrm.ToArray();
               }

           }

           
catch (Exception ex)
WinCE資料通訊之Web Service篇           
{
               
throw (ex);
           }

       }

      
WinCE資料通訊之Web Service篇       
/// 
       
/// 解壓縮Deflater資料
       
/// 
       
/// 壓縮過的byte[]資料
       
/// 解壓後的byte[]資料

       public static byte[] DeflaterDeCompress(byte[] input)
WinCE資料通訊之Web Service篇        
{
            
if (input == null)
WinCE資料通訊之Web Service篇            
{
                
throw new ArgumentNullException("null input");
            }

            
try
WinCE資料通訊之Web Service篇            
{
                Int32 mSize;
                
//int buffSize = 2048;
                byte[] buff = new byte[buffSize];
                
using (MemoryStream outmsStrm = new MemoryStream())
WinCE資料通訊之Web Service篇                
{
                    
using (InflaterInputStream mStream = new InflaterInputStream(new MemoryStream(input)))
WinCE資料通訊之Web Service篇                    
{
                        
while (true)
WinCE資料通訊之Web Service篇                        
{
                            mSize 
= mStream.Read(buff, 0, buff.Length);
                            
if (mSize > 0)
WinCE資料通訊之Web Service篇                            
{
                                outmsStrm.Write(buff, 
0, mSize);
                            }

                            
else
WinCE資料通訊之Web Service篇                            
{
                                
break;
                            }

                        }

                    }

                    
return outmsStrm.ToArray();
                }

            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                
throw (ex);
            }

        }

WinCE資料通訊之Web Service篇       
/// 
       
/// GZIP壓縮
       
/// 
       
/// 未壓縮的資料
       
/// GZIP壓縮後的資料

       public static byte[] GZipCompress(byte[] input)
WinCE資料通訊之Web Service篇       
{
           
if (input == null)
WinCE資料通訊之Web Service篇           
{
               
throw new ArgumentNullException("null input");
           }

           
try
WinCE資料通訊之Web Service篇           
{
               
using (MemoryStream outmsStrm = new MemoryStream())
WinCE資料通訊之Web Service篇               
{
                   
using (GZipOutputStream gzip = new GZipOutputStream(outmsStrm))
WinCE資料通訊之Web Service篇                   
{
                       gzip.Write(input, 
0, input.Length);
                   }

                   
return outmsStrm.ToArray();
               }

           }

           
catch (Exception ex)
WinCE資料通訊之Web Service篇           
{
               
throw (ex);
           }

       }

WinCE資料通訊之Web Service篇       
/// 
       
/// GZIP解壓縮
       
/// 
       
/// 壓縮過的資料
       
/// 解壓後的資料

       public static byte[] GZipDeCompress(byte[] input)
WinCE資料通訊之Web Service篇       
{
           
if (input == null)
WinCE資料通訊之Web Service篇           
{
               
throw new ArgumentNullException("null input");
           }

           
try
WinCE資料通訊之Web Service篇           
{
               
using (MemoryStream outmsStrm = new MemoryStream())
WinCE資料通訊之Web Service篇               
{
                   
using (GZipInputStream gzip = new GZipInputStream(new MemoryStream(input)))
WinCE資料通訊之Web Service篇                   
{
                       Int32 mSize;
                       
//int buffSize = 2048;
                       byte[] buff = new byte[buffSize];
                       
while (true)
WinCE資料通訊之Web Service篇                       
{
                           mSize 
= gzip.Read(buff, 0, buffSize);
                           
if (mSize > 0)
WinCE資料通訊之Web Service篇                           
{
                               outmsStrm.Write(buff, 
0, mSize);
                           }

                           
else
WinCE資料通訊之Web Service篇                           
{
                               
break;
                           }

                       }

                   }

                   
return outmsStrm.ToArray();
               }

           }

           
catch (Exception ex)
WinCE資料通訊之Web Service篇           
{
               
throw (ex);
           }

       }

WinCE資料通訊之Web Service篇       
/// 
       
/// ZIP壓縮資料
       
/// 
       
/// 待壓縮的資料
       
/// ZIP壓縮後的資料

       public static byte[] ZipCompress(byte[] input)
WinCE資料通訊之Web Service篇       
{
           
if (input == null)
WinCE資料通訊之Web Service篇           
{
               
throw new ArgumentNullException("null input");
           }

           
try
WinCE資料通訊之Web Service篇           
{
               
using (MemoryStream outmsStrm = new MemoryStream())
WinCE資料通訊之Web Service篇               
{
                   
using (ZipOutputStream zipStrm = new ZipOutputStream(outmsStrm))
WinCE資料通訊之Web Service篇                   
{
                       ZipEntry zn 
= new ZipEntry("znName");
                       zipStrm.PutNextEntry(zn);
                       zipStrm.Write(input, 
0, input.Length);
                   }

                   
return outmsStrm.ToArray();
               }

           }

           
catch (Exception ex)
WinCE資料通訊之Web Service篇           
{
               
throw (ex);
           }

       }

WinCE資料通訊之Web Service篇       
/// 
       
/// ZIP解壓縮資料
       
/// 
       
/// 壓縮過的資料
       
/// 解壓後的資料

       public static byte[] ZipDeCompress(byte[] input)
WinCE資料通訊之Web Service篇       
{
           
if (input == null)
WinCE資料通訊之Web Service篇           
{
               
throw new ArgumentNullException("null input");
           }

           
try
WinCE資料通訊之Web Service篇           
{
               
using (MemoryStream outmsStrm = new MemoryStream())
WinCE資料通訊之Web Service篇               
{
                   
using (ZipInputStream zipStrm = new ZipInputStream(new MemoryStream(input)))
WinCE資料通訊之Web Service篇                   
{
                       Int32 mSize;
                       
//int buffSize = 2048;
                       byte[] buff = new byte[buffSize];
                       ZipEntry zn 
= new ZipEntry("znName");
                       
while ((zn = zipStrm.GetNextEntry()) != null)
WinCE資料通訊之Web Service篇                       
{
                           
while (true)
WinCE資料通訊之Web Service篇                           
{
                               mSize 
= zipStrm.Read(buff, 0, buffSize);
                               
if (mSize > 0)
WinCE資料通訊之Web Service篇                               
{
                                   outmsStrm.Write(buff, 
0, mSize);
                               }

                               
else
WinCE資料通訊之Web Service篇                               
{
                                   
break;
                               }

                           }


                       }

                   }

                   
return outmsStrm.ToArray();
               }

           }

           
catch (Exception ex)
WinCE資料通訊之Web Service篇           
{
               
throw (ex);
           }

       }

      新增WebService服務

WinCE資料通訊之Web Service篇
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt        //方法二:返回 DataSet 物件用序列化後的byte[]位元組陣列
        [WebMethod(Description = "返回 DataSet 物件用序列化後的byte[]位元組陣列。")]
        
public byte[] GetDataSetBytes()
        {
            DataSet dataSet 
= GetNorthwindDataSet();
            
return ComZipClass.zip.byteXmlSerializer(dataSet);
        }

        
//方法三返回 DataSet物件用序列化並Bzip壓縮後的byte[]位元組陣列
        [WebMethod(Description = "返回 DataSet物件用序列化並Bzip壓縮後的byte[]位元組陣列。")]
        
public byte[] GetBZiipCompress()
        {
            DataSet dataSet 
= GetNorthwindDataSet();
            
byte[] ser = ComZipClass.zip.byteXmlSerializer(dataSet);
            
byte[] zip = ComZipClass.zip.BZipCompress(ser);
            
return zip;
        }
        [WebMethod(Description 
= "返回Deflater壓縮")]
        
public byte[] GetDeflaterCompress()
        {
            DataSet dataSet 
= GetNorthwindDataSet();
            
byte[] ser = ComZipClass.zip.byteXmlSerializer(dataSet);
            
//byte[] ser = ZipClass.zip.byteXmlSerializer(dataSet);
            byte[] zip = ComZipClass.zip.DeflaterCompress(ser);
            
return zip;
        }
        [WebMethod(Description 
= "返回Gzip壓縮")]
        
public byte[] GetGZipCompress()
        {
            DataSet dataSet 
= GetNorthwindDataSet();
            
byte[] ser = ComZipClass.zip.byteXmlSerializer(dataSet);
            
byte[] zip = ComZipClass.zip.GZipCompress(ser);
            
return zip;
        }
        [WebMethod(Description 
= "返回Zip壓縮")]
        
public byte[] GetZipCompress()
        {
            DataSet dataSet 
= GetNorthwindDataSet();
            
byte[] ser = ComZipClass.zip.byteXmlSerializer(dataSet);
            
byte[] zip = ComZipClass.zip.ZipCompress(ser);
            
return zip;
        }

     新增終端裝置呼叫

WinCE資料通訊之Web Service篇
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt //webmethod序列化資料
        private void btnSerial_Click(object sender, EventArgs e)
WinCE資料通訊之Web Service篇        
{
            
try
WinCE資料通訊之Web Service篇            
{
                
this.dtGrid.DataSource = null;
                DataSet ds 
= new DataSet();
                DateTime dtBegin 
= DateTime.Now;
                
byte[] datas = ws.GetDataSetBytes();
                DateTime dtDown 
= DateTime.Now;

                ds 
= (DataSet)ComZipClass.zip.objXmlDeserialize(datas, typeof(DataSet));
                DateTime dtSerial 
= DateTime.Now;
                
this.dtGrid.DataSource = ds.Tables[0];
                MessageBox.Show(
string.Format("下載耗時:{0},解壓序列化資料耗時:{1},繫結資料耗時:{2},資料量:{3}",
                dtDown 
- dtBegin,dtSerial-dtDown, DateTime.Now - dtDown, datas.Length));
            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                MessageBox.Show(ex.ToString());
            }

        }

        
//序列化並壓縮BZIP後資料
        private void btnBZip_Click(object sender, EventArgs e)
WinCE資料通訊之Web Service篇        
{
            
try
WinCE資料通訊之Web Service篇            
{
                
this.dtGrid.DataSource = null;
                DataSet ds 
= new DataSet();
                DateTime dtBegin 
= DateTime.Now;
                
byte[] datas = ws.GetBZiipCompress();
                DateTime dtDown 
= DateTime.Now;
                
byte[] uzip = ComZipClass.zip.BZipDeCompress(datas);
                DateTime dtUnzip 
= DateTime.Now;
                ds 
= (DataSet)ComZipClass.zip.objXmlDeserialize(uzip, typeof(DataSet));
                DateTime dtSerial 
= DateTime.Now;
                
this.dtGrid.DataSource = ds.Tables[0];
                 MessageBox.Show(
string.Format("下載耗時:{0},解壓BZIP耗時:{1},解壓序列化耗時:{2},繫結資料耗時:{3},資料量:{4}",
                dtDown 
- dtBegin, dtUnzip - dtDown, dtSerial - dtUnzip, DateTime.Now - dtSerial, datas.Length));
            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                MessageBox.Show(ex.ToString());
            }

        }

        
//序列化並壓縮Deflate後資料
        private void btnDeflater_Click(object sender, EventArgs e)
WinCE資料通訊之Web Service篇        
{
            
try
WinCE資料通訊之Web Service篇            
{
                
this.dtGrid.DataSource = null;
                DataSet ds 
= new DataSet();
                DateTime dtBegin 
= DateTime.Now;
                
byte[] datas = ws.GetDeflaterCompress();
                DateTime dtDown 
= DateTime.Now;
                
byte[] uzip = ComZipClass.zip.DeflaterDeCompress(datas);
                DateTime dtUnzip 
= DateTime.Now;
                ds 
= (DataSet)ComZipClass.zip.objXmlDeserialize(uzip, typeof(DataSet));
                DateTime dtSerial 
= DateTime.Now;
                
this.dtGrid.DataSource = ds.Tables[0];
                MessageBox.Show(
string.Format("下載耗時:{0},解壓Deflater耗時:{1},解壓序列化耗時:{2},繫結資料耗時:{3},資料量:{4}",
               dtDown 
- dtBegin, dtUnzip - dtDown, dtSerial - dtUnzip, DateTime.Now - dtSerial, datas.Length));
            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                MessageBox.Show(ex.ToString());
            }

        }

        
//序列化並壓縮GZIP後資料
        private void btnGZip_Click(object sender, EventArgs e)
WinCE資料通訊之Web Service篇        
{
            
try
WinCE資料通訊之Web Service篇            
{
                
this.dtGrid.DataSource = null;
                DataSet ds 
= new DataSet();
                DateTime dtBegin 
= DateTime.Now;
                
byte[] datas = ws.GetGZipCompress();
                DateTime dtDown 
= DateTime.Now;
                
byte[] uzip = ComZipClass.zip.GZipDeCompress(datas);
                DateTime dtUnzip 
= DateTime.Now;
                ds 
= (DataSet)ComZipClass.zip.objXmlDeserialize(uzip, typeof(DataSet));
                DateTime dtSerial 
= DateTime.Now;
                
this.dtGrid.DataSource = ds.Tables[0];
                MessageBox.Show(
string.Format("下載耗時:{0},解壓GZIP耗時:{1},解壓序列化耗時:{2},繫結資料耗時:{3},資料量:{4}",
               dtDown 
- dtBegin, dtUnzip - dtDown, dtSerial - dtUnzip, DateTime.Now - dtSerial, datas.Length));
            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                MessageBox.Show(ex.ToString());
            }

        }

        
//序列化並壓縮ZIP後資料
        private void btnZip_Click(object sender, EventArgs e)
WinCE資料通訊之Web Service篇        
{
            
try
WinCE資料通訊之Web Service篇            
{
                
this.dtGrid.DataSource = null;
                DataSet ds 
= new DataSet();
                DateTime dtBegin 
= DateTime.Now;
                
byte[] datas = ws.GetZipCompress();
                DateTime dtDown 
= DateTime.Now;
                
byte[] uzip = ComZipClass.zip.ZipDeCompress(datas);
                DateTime dtUnzip 
= DateTime.Now;
                ds 
= (DataSet)ComZipClass.zip.objXmlDeserialize(uzip, typeof(DataSet));
                DateTime dtSerial 
= DateTime.Now;
                
this.dtGrid.DataSource = ds.Tables[0];
                MessageBox.Show(
string.Format("下載耗時:{0},解壓ZIP耗時:{1},解壓序列化耗時:{2},繫結資料耗時:{3},資料量:{4}",
               dtDown 
- dtBegin, dtUnzip - dtDown, dtSerial - dtUnzip, DateTime.Now - dtSerial, datas.Length));
            }

            
catch (Exception ex)
WinCE資料通訊之Web Service篇            
{
                MessageBox.Show(ex.ToString());
            }

        }

      幾個測試壓縮資料dataset :268128;serial:269199;bzip:94561;Deflater:107049;gzip:108276;zip:108408;

      附上原始碼,解壓密碼暫不公開,有需要的留下Email。原始碼一  原始碼二

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/21255398/viewspace-604875/,如需轉載,請註明出處,否則將追究法律責任。

相關文章