.Net remoting, Webservice,WCF,Socket區別




傳統上,我們把計算機后台程序(Daemon)提供的功能,稱為"服務"(service)。比如,讓一個殺毒軟件在后台運行,它會自動監控系統,那么這種自動監控就是一個"服務"。
通俗地說,"服務"就是計算機可以提供的某一種功能。
  根據來源的不同,"服務"又可以分成兩種:一種是"本地服務"(使用同一台機器提供的服務,不需要網絡),另一種是"網絡服務"(使用另一台計算機提供的服務,必須通過
網絡才能完成)。"網絡服務"(Web Service)的本質,就是通過網絡調用其他網站的資源。舉例來說,去年公開課的時候我在ArcGIS Engine中調用過一個天氣預報的信息,並將信息和具體的位置關聯起來。所以,Web service讓你的網站可以使用其他網站的資源,比如在網頁上顯示天氣、地圖、twitter上的最新動態等等。
綜上:WebService是兩個計算機之間通訊(交談)的技術。並且現在炒的很火的SOA、雲計算在技術層面上都是WebService。
除了WebService 通訊外,系統間通訊有很多種技術,如像qq的這種Socket通訊在銀行系統中廣泛應用,.Net Remoting、DCom等通訊方式也應用很 多,
但是這些方式有如下缺點:
•        通訊數據格式不統一,同樣一個"你好"這樣的字符串在不同的協議中有不同的表示方法,異構系統集成很麻煩。一個系統一個模樣。
•        采用Socket、 .Net Remoting、DCom需要打開很多端口,而企業網絡安全的一個基本原則就是“盡可能少的打開端口”,很多企業網絡甚至嚴格規定“只能打開80端口”,
因此需要一種“跨防火牆”的技術(跨防火牆就是走80端口進行通訊)
•        這些通訊方式的協議是不開放的,要想知道服務提供了哪些方法、如何調用,必須能夠自描述
 
        
WSDL(Web Service Description Language) 

你會怎樣向別人介紹你的Web service有什么功能,以及每個函數調用時的參數呢?你可能會自己寫一套文檔,你甚至可能會口頭上告訴需要使用你的Web service的人。

這些非正式的方法至少都有一個嚴重的問題:當程序員坐到電腦前,想要使用你的Web service的時候,他們的工具(如Visual Studio)無法給他們提供任何幫助,因為這些工具根本就不了解你的Web service。解決方法是:用機器能閱讀的方式提供一個正式的描述文檔。Web service描述語言(WSDL)就是這樣一個基於XML的語言,用於描述Web service及其函數、參數和返回值。因為是基於XML的,所以WSDL既是機器可閱讀的,又是人可閱讀的,這將是一個很大的好處。一些最新的開發工具既能根據你的Web service生成WSDL文檔,又能導入WSDL文檔,生成調用相應Web service的代碼

Web服務器描述語言是用XML文檔來描述Web服務的標准,是Web服務的接口定義語言,由Ariba、Intel、IBM、MS等共同提出,通過WSDL,可描述Web服務的三個基本屬性:
·服務做些什么——服務所提供的操作(方法)
·如何訪問服務——和服務交互的數據格式以及必要協議
·服務位於何處——協議相關的地址,如URL

 

XML和XSD 
可擴展的標記語言(XML)是Web service平台中表示數據的基本格式。除了易於建立和易於分析外,XML主要的優點在於它既是平台無關的,又是廠商無關的。無關性是比技術優越性更重要的:軟件廠商是不會選擇一個由競爭對手所發明的技術的。 
XML解決了數據表示的問題,但它沒有定義一套標准的數據類型,更沒有說怎么去擴展這套數據類型。例如,整形數到底代表什么?16位,32位,還是64位?這些細節對實現互操作性都是很重要的。W3C制定的XML Schema(XSD)就是專門解決這個問題的一套標准。它定義了一套標准的數據類型,並給出了一種語言來擴展這套數據類型。Web service平台就是用XSD來作為其數據類型系統的。當你用某種語言(如VB.NET或C#)來構造一個Web service時,為了符合Web service標准,所有你使用的數據類型都必須被轉換為XSD類型。你用的工具可能已經自動幫你完成了這個轉換,但你很可能會根據你的需要修改一下轉換過程。在第二章中,我們將深入XSD,學習怎樣轉換自定義的數據類型(例如類)到XSD的類型。 

SOAP 
Web service建好以后,你或者其他人就會去調用它。簡單對象訪問協議(SOAP)提供了標准的RPC方法來調用Web service。實際上,SOAP在這里有點用詞不當:它意味着下面的Web service是以對象的方式表示的,但事實並不一定如此:你完全可以把你的Web service寫成一系列的C函數,並仍然使用SOAP進行調用。SOAP規范定義了SOAP消息的格式,以及怎樣通過HTTP協議來使用SOAP。SOAP也是基於XML和XSD的,XML是SOAP的數據編碼方式。第三章我們會討論SOAP,並結識SOAP消息的各種元素。 

綜上我們還可以得出以下結論:

請求、返回的XML數據格式(有哪些節點、節點的名字等等)WebService 用SOAP協議進行規定,方法描述信息XML用WSDL協議規定。WebService技術是與語言、平台無關,因此.net可以訪問java編寫的WebService、java也可以訪問.net編寫的webservice,php、python等各種語言也幾乎都支持webservice,因此可以說webservice可以實現跨語言方法調用。

但是如果自己構建請求、返回xml,解析xml請求,自己負責方法描述信息更新是很麻煩的,.net就提供了簡化開發WebService。 

WebService的創建和使用

WebService的使用過程包括服務器端代碼的編寫和客戶端代碼的調用,服務器端的代碼比較容易,只是在使用的時候需要添加一些[WebService]和[WebMethod]這樣的標記

 1、  服務器端(ServerWeb):就想寫普通方法一樣,不需要處理請求、響應。服務器端新建“Web服務”(asmx),在遠端可以調用的方法上標注[WebMethod]。

 

using System;   
using System.Linq;   
using System.Web;   
using System.Web.Services;   
using System.Web.Services.Protocols;   
using System.Xml.Linq;   
[WebService(Namespace = "http://tempuri.org/")]   
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]   
// 若要允許使用 ASP.NET AJAX 從腳本中調用此 Web 服務,請取消對下行的注釋。   
// [System.Web.Script.Services.ScriptService]   
public class Service : System.Web.Services.WebService   
{   
    public Service () {   
        //如果使用設計的組件,請取消注釋以下行    
        //InitializeComponent();    
    }   
    //[WebMethod]   
    //public string HelloWorld()   
    //{   
    //    return "Hello World";   
    //}   
    [WebMethod(Description = "求和的方法")]   
    public double addition(double i, double j)   
    {   
        return i + j;   
    }   
    [WebMethod(Description = "求差的方法")]   
    public double subtract(double i, double j)   
    {   
        return i - j;   
    }   
    [WebMethod(Description = "求積的方法")]   
    public double multiplication(double i, double j)   
    {   
        return i * j;   
    }   
    [WebMethod(Description = "求商的方法")]   
    public double division(double i, double j)   
    {   
        if (j != 0)   
            return i / j;   
        else  
            return 0;   
    }   
}  

 

 

 2、客戶端添加對asmx的“服務器引用”,然后就可以調用***SoapClient類中的方法。就“好像”直接調用了服務端的方法(因為VS2010中有兩種添加服務的方法,一種是早期的針對net2.0的,如果是2.0的話,會生成一個跟服務端同類名的類)。

 

添加服務引用的時候工具讀取asmx的WSDL自動生成了ServiceReference1中的類,這些類幫我們來拼Http請求,並且把Http返回值拆成函數的返回。

客戶端“添加服務引用”,填寫asmx的地址。然后就可以調用Service References下自動生成的***SoapClient類了。

用WebService的時候如果服務端的接口定義發生變化,則需要重新添加對服務端的引用,因為Service References中的類是工具讀取WSDL定義自動生成的。在服務引用上點擊右鍵,選擇“更新服務引用”。如果只是修改了WebService內部實現,而接口沒變,則不需要“更新服務引用”,因為WSDL沒變,Soap沒變。    

 static void Main(string[] args)
        {
            ServiceTest.ServiceSoapClient stsoap = new ServiceTest.ServiceSoapClient();

           double c= stsoap.addition(1, 2);
           Console.WriteLine(c.ToString());

            // vs 2010中兩種方式
            ServiceTest.Service st = new ServiceTest.Service();

            double a = st.addition(1, 2);

            Console.WriteLine(a.ToString());

            Console.ReadKey();
        }

 

 

 

.Net remoting

 

Net remoting 是簡化網絡通訊的技術,底層仍然是TCP等東西。

remoting要添加對System.Runtime.Remoting的引用

編寫服務接口類庫項目,正常寫法!WebService中WSDL相當於對服務端方法的描述;.net Remoting中走的是二進制數據,因此必須一個描述服務端方法的接口類庫。這個類庫里面往往是一個接口,定義了服務器端實現方法的方法名,客戶端和服務器端都需要引進用這個接口。

服務端實現服務接口,繼承自MarshalByRefObject,然后運行備注中的代碼注冊服務。

客戶端代碼在備注中

Remoting和WebService的區別:Remoting效率高,走的是普通TCP, WebService則是Http協議,需要IIS、ASP.Net、XML解析等,效率低。Remoting適合於內網通訊, WebService適合於外網通訊。

除非項目要求,否則以后盡量用WCF。.Net Remoting是微軟私有協議,因此如果要跨平台調用還是普通Socket或者WebService。

用法說明:

 1、新建接口項目,定義服務接口。

注意:remoting要添加對System.Runtime.Remoting的引用

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NETRemotiongInterface
{
    public interface IRemotingTest
    {
        double add(double a,double b);
    }
}

 

 

 

2、新建服務器端項目(控制台的,或者WinForm,或者Windows服務等)

定義實現服務接口的類,還要繼承繼承自MarshalByRefObject類

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NETRemotiongInterface;

namespace RemotingServer
{
    class TestServiceImp : MarshalByRefObject,IRemotingTest
{ #region IRemotingTest 成員 public double add(double a, double b) { return a + b; } #endregion } }

 

 

 

3,服務器啟動時調用

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;

namespace RemotingServer
{
    class Program
    {
        static void Main(string[] args)
        {

             TcpChannel tcpChannel = new TcpChannel(9999);

            ChannelServices.RegisterChannel(tcpChannel);

 

            //注冊服務:第一個參數為服務的實現類,第二個參數為服務的名字。

            RemotingConfiguration.RegisterWellKnownServiceType(typeof(TestServiceImp),

                "test", WellKnownObjectMode.Singleton);

 

   //注冊服務。如果控制台程序,控制不要讓程序退出,

            //主要目的是不要讓服務器退出

            while (true)

            {

                string s = Console.ReadLine();

                if (s == "quit")

                {

                    return;

                }

            }
        }
    }
}
 

,4、客戶端:新建客戶端項目,引用服務接口

 

namespace RemotingClient
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpChannel tcpChannel = new TcpChannel();

            ChannelServices.RegisterChannel(tcpChannel, false);

            IRemotingTest test =
                (IRemotingTest)Activator.GetObject(typeof(IRemotingTest), "tcp://127.0.0.1:9999/test");//第一個參數為服務實現的接口,第二個參數為服務的地址:最后一部分是服務在服務器端RegisterWellKnownServiceType時第二個參數的名字然后就可以調用服務端方法了。
            double a = test.add(1, 2);
            Console.WriteLine(a.ToString());
            Console.ReadKey();
 
        }
    }
}

 

從WebService和NetRemoting來看客戶端都要知道服務器端暴露的功能,這個是必須的,要不然客戶端怎么調用,WS是通過一個地址,而NetRemoting是通過一個接口類庫,當然這也只是表面現象。

                                                                 WCF

WCF(Windows Communication foundation)是微軟的統一網絡通訊開發的技術,無論底層用.Net Remoting還是WebService還是Restful還是MSMQ等,只要修改配置文件即可。所以WCF並不是新技術。

WCF和.Net Remoting、WebService等技術的關系就像ADO.Net和SQLServer、Oracle驅動的關系一樣。通過VS的“WCF服務配置編輯器”簡化配置,修改不同的協議。

一開始內網運行就行,后來想運行到公網,那么如果一開始用.net remoting寫后來改成WebService還是有工作量的,因為寫法不一樣,但是用WCF就不一樣了。

新建“WCF服務庫”,WCF服務庫可以Host在IIS上、單獨的WinForm程序等。

WCF、.Net Remoting和WebService的關系: .Net Remoting是普通的TCP通訊,適合於局域網,效率高; WebService是基於Http協議,適合於廣域網,效率低;WCF是對.Net Remoting、 WebService等的簡化、統一,可以通過配置來切換不同的底層實現,代碼幾乎不用動。

 

關於WCF的例子,我也懶得寫了,給出一篇博文,大家可以自行研究:http://www.cnblogs.com/oec2003/archive/2010/07/15/1778013.html

 

Socket的例子我們可能見得比較多,這里就不羅嗦了,啰嗦了,直接上代碼:

 

服務器端

 

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class SynchronousSocketClient {

    public static void StartClient() {
        // Data buffer for incoming data.
        byte[] bytes = new byte[1024];

        // Connect to a remote device.
        try {
            // Establish the remote endpoint for the socket.
            // This example uses port 11000 on the local computer.
            IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName())
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(ipAddress,11000);

            // Create a TCP/IP  socket.
            Socket sender = new Socket(AddressFamily.InterNetwork, 
                SocketType.Stream, ProtocolType.Tcp );

            // Connect the socket to the remote endpoint. Catch any errors.
            try {
                sender.Connect(remoteEP);

                Console.WriteLine("Socket connected to {0}",
                    sender.RemoteEndPoint.ToString());

                // Encode the data string into a byte array.
                byte[] msg = Encoding.ASCII.GetBytes("This is a test<EOF>");

                // Send the data through the socket.
                int bytesSent = sender.Send(msg);

                // Receive the response from the remote device.
                int bytesRec = sender.Receive(bytes);
                Console.WriteLine("Echoed test = {0}",
                    Encoding.ASCII.GetString(bytes,0,bytesRec));

                // Release the socket.
                sender.Shutdown(SocketShutdown.Both);
                sender.Close();
                
            } catch (ArgumentNullException ane) {
                Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
            } catch (SocketException se) {
                Console.WriteLine("SocketException : {0}",se.ToString());
            } catch (Exception e) {
                Console.WriteLine("Unexpected exception : {0}", e.ToString());
            }

        } catch (Exception e) {
            Console.WriteLine( e.ToString());
        }
    }
    
    public static int Main(String[] args) {
        StartClient();
        return 0;
    }
}

 

客戶端

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class SynchronousSocketListener {
    
    // Incoming data from the client.
    public static string data = null;

    public static void StartListening() {
        // Data buffer for incoming data.
        byte[] bytes = new Byte[1024];

        // Establish the local endpoint for the socket.
        // Dns.GetHostName returns the name of the 
        // host running the application.
        IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

        // Create a TCP/IP socket.
        Socket listener = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp );

        // Bind the socket to the local endpoint and 
        // listen for incoming connections.
        try {
            listener.Bind(localEndPoint);
            listener.Listen(10);

            // Start listening for connections.
            while (true) {
                Console.WriteLine("Waiting for a connection");
                // Program is suspended while waiting for an incoming connection.
                Socket handler = listener.Accept();
                data = null;

                // An incoming connection needs to be processed.
                while (true) {
                    bytes = new byte[1024];
                    int bytesRec = handler.Receive(bytes);
                    data += Encoding.ASCII.GetString(bytes,0,bytesRec);
                    if (data.IndexOf("<EOF>") > -1) {
                        break;
                    }
                }

                // Show the data on the console.
                Console.WriteLine( "Text received : {0}", data);

                // Echo the data back to the client.
                byte[] msg = Encoding.ASCII.GetBytes(data);

                handler.Send(msg);
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }
            
        } catch (Exception e) {
            Console.WriteLine(e.ToString());
        }

        Console.WriteLine("\nPress ENTER to continue");
        Console.Read();
        
    }

    public static int Main(String[] args) {
        StartListening();
        return 0;
    }
}

 

 

 

 

來點這四個的總結的話。

 

1:socket VS remoting

 

    使用socket無疑是效率最高的。但是,在復雜的接口環境下,socket的開發效率也是最低的。故在兼顧開發效率的情況下,可以使用remoting來代替socket開發。並且:
    1、Tcp通道的Remoting速度非常快。
    你可以通過端口查看工具,發現remoting比直接socket傳輸的內容,應該是屬於同一個數量級的。我的另一個擔心是,大客戶端數量的情況下,remoting傳輸效率會不會很低,結果經過現場測試,同時對300個客戶端進行數據通信,不存在信息丟失情況。
    2、雖然是遠程的,但是非常接近於本地調用對象。
    也就是完全符合面向對象思想。
    3、可以做到保持對象的狀態
    直接使用socket傳輸機制,我們必須花大量的精力來處理異常、斷網、死機等現象,使用remoting,這些工作會大大簡化。

 

2:remoting vs webservice 
    1、webservice在framework2.0狀態下只能寄宿於IIS等應用服務器中。微軟直到3.0才提供了servicehost來寄宿 webservice,這就極大地限制了webservice在使用中的靈活性。在framework2.0環境下,如果你有一個應用要脫離IIS而存 在,就不得不拋棄webservice。(除非你想代碼實現一個WEB應用服務器)

    2、remoting可寄宿在你自己的代碼中,也可寄宿在windows服務及IIS中。最大程度的提供了開發和部署的靈活性。
    3、remoting在使用http通道的時候,也如webservice一樣支持穿透路由。
    4、remoting與websercie相比,提供雙向通信。哪怕是將remoting寄宿在IIS中,也支持。
    5、webservice客戶端自動生成的代理類比較復雜。而remoting一般來說,都是手動編寫客戶端代碼。
    6、當然,webservice最主要優勢是,它是一個行業標准,而remoting只是微軟自己內部的標准,如果你的應用要脫離微軟的平台,就只能使用webservice了。

    7,NetRemoting的優點是用戶既可以使用TCP信道方式進行二進制流方式通信,也可以使用HTTP信道進行SOAP格式的性通信,而WebService只能使用HTTP通道

    8, NetRemotiong效率相對WebService要高不少;

    9, Netremoting可以用於有狀態的情況,而WebService只能使用無狀態的情況。

 

3:remoting vs wcf
    與wcf的比較,更多的是從平台的普及度上來說。在當前環境下,2.0的普及度還是最高的。如果哪一天3.0甚至4.0普及了,當然WCF是最好的。

參考:http://evencode.iteye.com/blog/1453046

        http://www.cnblogs.com/oec2003/archive/2010/07/15/1778013.html

        http://blog.csdn.net/zhoufoxcn/article/details/1649776

       http://blog.csdn.net/huangxinfeng/article/details/4967629

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM