<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      我的WCF之旅(3):在WCF中實現(xiàn)雙工通信

      雙工(Duplex)模式的消息交換方式體現(xiàn)在消息交換過程中,參與的雙方均可以向?qū)Ψ桨l(fā)送消息。基于雙工MEP消息交換可以看成是多個基本模式下(比如請求-回復(fù)模式和單項模式)消息交換的組合。雙工MEP又具有一些變體,比如典型的訂閱-發(fā)布模式就可以看成是雙工模式的一種表現(xiàn)形式。雙工消息交換模式使服務(wù)端回調(diào)(Callback)客戶端操作成為可能。

      一、兩種典型的雙工MEP

      1.請求過程中的回調(diào)

      這是一種比較典型的雙工消息交換模式的表現(xiàn)形式,客戶端在進(jìn)行服務(wù)調(diào)用的時候,附加上一個回調(diào)對象;服務(wù)在對處理該處理中,通過客戶端附加的回調(diào)對象(實際上是調(diào)用回調(diào)服務(wù)的代理對象)回調(diào)客戶端的操作(該操作在客戶端執(zhí)行)。整個消息交換的過程實際上由兩個基本的消息交換構(gòu)成,其一是客戶端正常的服務(wù)請求,其二則是服務(wù)端對客戶端的回調(diào)。兩者可以采用請求-回復(fù)模式,也可以采用單向(One-way)的MEP進(jìn)行消息交換。圖1描述了這樣的過程,服務(wù)調(diào)用和回調(diào)都采用請求-回復(fù)MEP。



      圖1 請求過程中的回調(diào)

      2.訂閱-發(fā)布

      訂閱-發(fā)布模式是雙工模式的一個典型的變體。在這個模式下,消息交換的雙方變成了訂閱者和發(fā)布者,若干訂閱者就某個主題向發(fā)布者申請訂閱,發(fā)布者將所有的訂閱者保存在一個訂閱者列表中,在某個時刻將主題發(fā)送給該主題的所有訂閱者。實際上基于訂閱-發(fā)布模式的消息交換也可以看成是兩個基本模式下消息交換的組合,申請訂閱是一個單向模式的消息交換(如果訂閱者行為得到訂閱的回饋,該消息交換也可以采用請求-回復(fù)模式);而主題發(fā)布也是一個基于單向模式的消息交換過程。訂閱-發(fā)布消息交換模式如圖2所示。


      圖2 訂閱-發(fā)布

       

      二、實例演示:創(chuàng)建基于雙工通信的WCF應(yīng)用

      接下來我們通過一個的案例演示基于雙工通信的WCF應(yīng)用。為簡單起見,我們沿用計算服務(wù)的例子。在這之前,我們都是調(diào)用CalculuateService直接得到計算結(jié)果,并將計算結(jié)果通過控制臺輸出。在本例中我們將采用另外一種截然不同的方式調(diào)用服務(wù)并進(jìn)行結(jié)果的輸出:我們通過單向(One-way)的模式調(diào)用CalculuateService(也就是客戶端不可能通過回復(fù)消息得到計算結(jié)果),服務(wù)端在完成運算結(jié)果后,通過回調(diào)(Callback)的方式在客戶端將計算結(jié)果打印出來。整個應(yīng)用的層次仍然采用我們一貫的4層結(jié)構(gòu):Contracts、Services、Hosting和Clients,如圖3所示。


      圖3 雙工通信案例應(yīng)用結(jié)構(gòu)

       

      步驟一:定義服務(wù)契約和回調(diào)契約

      首先進(jìn)行服務(wù)契約的定義,我們照例通過接口(ICalculator)的方式定義服務(wù)契約,作用于指定加法運算的Add操作,我們通過OperationContractAttribute特性的IsOneway屬性將操作定義成單向的操作,這意味著客戶端僅僅是向服務(wù)端發(fā)送一個運算的請求,并不會通過回復(fù)消息得到任何運算結(jié)果。

         1: using System.ServiceModel;
         2: namespace Artech.DuplexServices.Contracts
         3: {
         4:     [ServiceContract(Namespace="http://www.artech.com/",
         5: CallbackContract=typeof(ICallback))]
         6:     public interface ICalculator
         7:     {
         8:         [OperationContract(IsOneWay=true)]
         9:         void Add(double x, double y);
        10:     }
        11: }

      我們試圖實現(xiàn)的是通過在服務(wù)端回調(diào)客戶端操作的方式實現(xiàn)運算結(jié)果的輸出。客戶端調(diào)用CalculatorService正常的服務(wù)調(diào)用,那么在服務(wù)執(zhí)行過程中借助于客戶端在服務(wù)調(diào)用時提供的回調(diào)對象對客戶端的操作進(jìn)行回調(diào),從本質(zhì)上講是另外一種形式的服務(wù)調(diào)用。WCF采用基于服務(wù)契約的調(diào)用形式,客戶端正常的服務(wù)調(diào)用需要服務(wù)契約,同理服務(wù)端回調(diào)客戶端依然需要通過描述回調(diào)操作的服務(wù)契約,我們把這種服務(wù)契約稱為回調(diào)契約。回調(diào)契約的類型通過ServiceContractAttribute特性的CallbackContract屬性進(jìn)行指定。

      上面代碼中服務(wù)契約ICalculator的回調(diào)契約ICallback定義如下。由于回調(diào)契約本質(zhì)也是一個服務(wù)契約,所以定義方式和一般意義上的服務(wù)契約基本一樣。有一點不同的是,由于定義ICalculator的時候已經(jīng)通過[ServiceContract(CallbackContract=typeof(ICallback))]指明ICallback是一個服務(wù)契約了,所以ICallback不再需要添加ServiceContractAttribute特性。ICallback定義了一個服務(wù)操作DisplayResult用于顯示運算結(jié)果(前兩個參數(shù)為執(zhí)行加法運算的操作數(shù)),由于服務(wù)端不需要回調(diào)的返回值,索性將回調(diào)操作也設(shè)為單向方法。

         1: using System.ServiceModel;
         2: namespace Artech.DuplexServices.Contracts
         3: {
         4:     public interface ICallback
         5:     {
         6:         [OperationContract(IsOneWay=true)]
         7:         void DisplayResult(double x, double y, double result);
         8:     }
         9: }

      步驟二:實現(xiàn)服務(wù)

      在實現(xiàn)了上面定義的服務(wù)契約ICalculator的服務(wù)CalculatorService中,實現(xiàn)了Add操作,完成運算和結(jié)果顯示的工作。結(jié)果顯示是通過回調(diào)的方式實現(xiàn)的,所以需要借助于客戶端提供的回調(diào)對象(該對象在客戶端調(diào)用CalculatorService的時候指定,在介紹客戶端代碼的實現(xiàn)的時候會講到)。在WCF中,回調(diào)對象通過當(dāng)前OperationContext的GetCallback<T>方法獲得(T代表回調(diào)契約的類型)。

         1: using Artech.DuplexServices.Contracts;
         2: using System.ServiceModel;
         3: namespace Artech.DuplexServices.Services
         4: {
         5:     public class CalculatorService : ICalculator
         6:     {
         7:         #region ICalculator Members
         8:  
         9:         public void Add(double x, double y)
        10:         {
        11:             double result = x + y;
        12:             ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
        13:             callback.DisplayResult(x, y, result);
        14:         }
        15:  
        16:         #endregion
        17:     }
        18: } 

      注: OperationContext在WCF中是一個非常重要、也是一個十分有用的對象,它代表服務(wù)操作執(zhí)行的上下文。我們可以通過靜態(tài)屬性Current(OperationContext.Current)得到當(dāng)前的OperationContext。借助OperationContext,我們可以在服務(wù)端或者客戶端獲取或設(shè)置一些上下文,比如在客戶端可以通過它為出棧消息(outgoing message)添加SOAP報頭,以及HTTP報頭(比如Cookie)等。在服務(wù)端,則可以通過OperationContex獲取在客戶端設(shè)置的SOAP報頭和HTTP報頭。關(guān)于OperationContext的詳細(xì)信息,可以參閱MSDN在線文檔。

      步驟三:服務(wù)寄宿

      我們通過一個控制臺應(yīng)用程序完成對CalculatorService的寄宿工作,并將所有的服務(wù)寄宿的參數(shù)定義在配置文件中。由于雙工通信依賴于一個雙工的信道棧,即依賴于一個能夠支持雙工通信的綁定,在此我們選用了NetTcpBinding。

         1: <?xml version="1.0" encoding="utf-8" ?>
         2: <configuration>
         3:     <system.serviceModel>
         4:         <behaviors>
         5:         <services>
         6:             <service name="Artech.DuplexServices.Services.CalculatorService">
         7:                 <endpoint address="net.tcp://127.0.0.1:9999/CalculatorService"
         8:                     binding="netTcpBinding" contract="Artech.DuplexServices.Contracts.ICalculator" />
         9:             </service>
        10:         </services>
        11: </system.serviceModel>
        12: </configuration>

      注: 在WCF預(yù)定義綁定類型中,WSDualHttpBindingNetTcpBinding均提供了對雙工通信的支持,但是兩者在對雙工通信的實現(xiàn)機制上卻有本質(zhì)的區(qū)別。WSDualHttpBinding是基于HTTP傳輸協(xié)議的;而HTTP協(xié)議本身是基于請求-回復(fù)的傳輸協(xié)議,基于HTTP的通道本質(zhì)上都是單向的。WSDualHttpBinding實際上創(chuàng)建了兩個通道,一個用于客戶端向服務(wù)端的通信,而另一個則用于服務(wù)端到客戶端的通信,從而間接地提供了雙工通信的實現(xiàn)。而NetTcpBinding完全基于支持雙工通信的TCP協(xié)議。

         1: using System;
         2: using System.ServiceModel;
         3: using Artech.DuplexServices.Services;
         4: namespace Artech.DuplexServices.Hosting
         5: {
         6:     class Program
         7:     {
         8:         static void Main(string[] args)
         9:         {
        10:             using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
        11:             {
        12:                 host.Open();
        13:                 Console.Read();
        14:             }
        15:         }
        16:     }
        17: }

      步驟四:實現(xiàn)回調(diào)契約

      在客戶端程序為回調(diào)契約提供實現(xiàn),在下面的代碼中CalculateCallback實現(xiàn)了回調(diào)契約ICallback,在DisplayResult方法中對運算結(jié)果進(jìn)行輸出。

         1: using System;
         2: using Artech.DuplexServices.Contracts;
         3: namespace Artech.DuplexServices.Clients
         4: {
         5:     class CalculateCallback:ICallback
         6:     {
         7:  
         8:         public void DisplayResult(double x, double y, double result)
         9:         {
        10:             Console.WriteLine("x + y = {2} when x = {0} and y = {1}", x, y, result);
        11:         }
        12:     }
        13: }

      步驟五:服務(wù)調(diào)用

      接下來實現(xiàn)對雙工服務(wù)的調(diào)用,下面是相關(guān)的配置和托管程序。在服務(wù)調(diào)用程序中,通過DuplexChannelFactory<TChannel>創(chuàng)建服務(wù)代理對象,DuplexChannelFactory<TChannel>和ChannelFactory<TChannel>的功能都是一個服務(wù)代理對象的創(chuàng)建工廠,不過DuplexChannelFactory<TChannel>專門用于基于雙工通信的服務(wù)代理的創(chuàng)建。在創(chuàng)建DuplexChannelFactory<TChannel>之前,先創(chuàng)建回調(diào)對象,并通過InstanceContext對回調(diào)對象進(jìn)行包裝。

         1: <?xml version="1.0" encoding="utf-8" ?>
         2: <configuration>
         3:     <system.serviceModel>
         4:         <client>
         5:             <endpoint name="CalculatorService" address="net.tcp://127.0.0.1:9999/CalculatorService" binding="netTcpBinding" contract="Artech.DuplexServices.Contracts.ICalculator" />
         6:         </client>
         7:     </system.serviceModel>
         8: </configuration>
         1: using System;
         2: using Artech.DuplexServices.Contracts;
         3: using System.ServiceModel;
         4: namespace Artech.DuplexServices.Clients
         5: {
         6:     class Program
         7:     {
         8:         static void Main(string[] args)
         9:         {
        10:             InstanceContext instanceContext = new InstanceContext(new CalculateCallback());
        11:             using(DuplexChannelFactory<ICalculator> channelFactory = new  DuplexChannelFactory<ICalculator>(instanceContext,"CalculatorService"))
        12:             {
        13:                 ICalculator proxy = channelFactory.CreateChannel();
        14:                 using (proxy as IDisposable)
        15:                 {
        16:                     proxy.Add(1, 2);
        17:                     Console.Read();
        18:                 }
        19:             }
        20:         }
        21:     }
        22: }

      在服務(wù)寄宿程序啟用的情況下,運行客戶端程序后,通過服務(wù)端執(zhí)行的運算結(jié)果會通過回調(diào)客戶端的操作顯示出來,下面是最終輸出的結(jié)果。

      x + y = 3 when x = 1 and y = 2

      三、特別注意

      接下來我們將針對上面這個案例,討論一些關(guān)于雙工服務(wù)的細(xì)節(jié)性問題。

      問題1:回調(diào)對雙工信道的依賴

      在本案例中,由于使用的NetTcpBinding,所以我們底層采用的是TCP協(xié)議。由于TCP協(xié)議是一個基于連接的傳輸協(xié)議,只有當(dāng)通信雙方的連接被成功創(chuàng)建出來后,他們之間才能進(jìn)行正常的消息傳輸。

      在上面給出的客戶端代碼中,在調(diào)用了Add方法后添加了這樣的語句“Console.Read();”,這是為了阻止調(diào)用proxy的Dispose方法,因為該方法將會試圖關(guān)閉底層的TCP連接。由于服務(wù)端的回調(diào)操作也會使用該TCP連接,如果在回調(diào)操作尚未執(zhí)行完畢就試圖關(guān)閉網(wǎng)絡(luò)連接,將會導(dǎo)致回調(diào)無法正常執(zhí)行。所以如果我們將該語句去掉,將會拋出如圖4所示的ProtocolException異常。

         1: InstanceContext instanceContext = new InstanceContext(new CalculateCallback());
         2: using(DuplexChannelFactory<ICalculator> channelFactory = new  DuplexChannelFactory<ICalculator>(instanceContext,"CalculatorService"))
         3: {
         4:     ICalculator proxy = channelFactory.CreateChannel();
         5:     using (proxy as IDisposable)
         6:     {
         7:         proxy.Add(1, 2);
         8:         //Console.Read();
         9:     }
        10: }

       


      圖4 關(guān)閉服務(wù)代理導(dǎo)致的ProtocolException異常

      問題2:回調(diào)導(dǎo)致的死鎖

      第2個問題是關(guān)于并發(fā)的問題,我們先看表現(xiàn)出來的現(xiàn)象,再分析原因并找出解決方案。現(xiàn)在我們修改一下回調(diào)契約,將OperationContractAttribute的IsOneWay屬性去掉,將Add操作由單向操作改成傳統(tǒng)意義的請求-回復(fù)服務(wù)操作。運行系統(tǒng),將會拋出如圖5所示的InvalidOperationException異常。

         1: using System.ServiceModel;
         2: namespace Artech.DuplexServices.Contracts
         3: {
         4:     public interface ICallback
         5:     {
         6:         [OperationContract]
         7:         void DisplayResult(double x, double y, double result);
         8:     }
         9: }


      圖5 雙工通信的并發(fā)、死鎖

       

      異常的消息已經(jīng)道出了出錯的原因和解決方案,不過可能是由于Visual Studio漢化的原因,顯示的出錯消息顯得有點不知所以。究其本質(zhì),這是一個死鎖導(dǎo)致的異常,由于默認(rèn)的情況是服務(wù)的執(zhí)行按Single并發(fā)模式進(jìn)行,也就是說在服務(wù)執(zhí)行全程,服務(wù)對象只能被一個線程訪問。WCF通過加鎖機制保證服務(wù)對象的獨占性使用,也就是說在服務(wù)執(zhí)行開始會對服務(wù)對象加鎖,該鎖在服務(wù)操作結(jié)束之后釋放。

      回到我們的例子,在Add操作執(zhí)行過程中,服務(wù)端回調(diào)客戶端操作進(jìn)行運算結(jié)果的顯示工作。如果回調(diào)是采用單向操作,回調(diào)請求一經(jīng)發(fā)送便會返回,服務(wù)操作可以繼續(xù)得到執(zhí)行直到操作正常結(jié)束。但是服務(wù)采用請求-回復(fù)模式的回調(diào),服務(wù)端會一直等待回調(diào)操作的返回。而另一方面,當(dāng)回調(diào)操作在客戶端正常執(zhí)行后,回到服務(wù)端試圖訪問服務(wù)操作的時候,發(fā)現(xiàn)對象被服務(wù)操作執(zhí)行的線程鎖住,所以它會等待服務(wù)操作的執(zhí)行完成后將鎖釋放。這樣,服務(wù)操作需要等待回調(diào)操作進(jìn)行正常返回以便執(zhí)行后續(xù)操作,而回調(diào)操作只有等待服務(wù)操作執(zhí)行完畢將鎖釋放才能得以返回,從而形成了死鎖。

      解決方法就是通過服務(wù)行為改變服務(wù)執(zhí)行的并發(fā)模式,在下面的代碼中我們在服務(wù)類型(CalculatorService)中通過ServiceBehaviorAttribute特性的ConcurrencyMode屬性將并發(fā)模式設(shè)為Reentrant或者M(jìn)ultiple均可以解決這個問題。關(guān)于WCF中的并發(fā)是一個重要而且復(fù)雜的話題,本書的下卷會對其進(jìn)行單獨的介紹。

         1: [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
         2: public class CalculatorService : ICalculator
         3: {
         4:     //省略實現(xiàn)
         5: }
         1: [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
         2: public class CalculatorService : ICalculator
         3: {
         4:     //省略實現(xiàn)
         5: }

      問題3:如果采用WsDualHttpBinding?

      接下來我們來看關(guān)于雙工服務(wù)的第3個問題。我們這個案例采用NetTcpBinding作為終結(jié)點的綁定類型。現(xiàn)在我們采用基于HTTP的WSDualHttpBinding看看我們的應(yīng)用能否正常運行。我們需要做的僅僅是改變服務(wù)端和客戶端的配置。

         1: <?xml version="1.0" encoding="utf-8" ?>
         2: <configuration>
         3:     <system.serviceModel>
         4:         <behaviors>
         5:         <services>
         6:             <service name="Artech.DuplexServices.Services.CalculatorService">
         7:                 <endpoint address="http://127.0.0.1:9999/CalculatorService"
         8:                     binding="wsDualHttpBinding" contract="Artech.DuplexServices.Contracts.ICalculator" />
         9:             </service>
        10:         </services>
        11: </system.serviceModel>
        12: </configuration>
         1: <?xml version="1.0" encoding="utf-8" ?>
         2: <configuration>
         3:     <system.serviceModel>
         4:         <client>
         5:             <endpoint name="CalculatorService" address=" 
         6: http://127.0.0.1:9999/CalculatorService" binding=" wsDualHttpBinding" contract="Artech.DuplexServices.Contracts.ICalculator" />
         7:         </client>
         8:     </system.serviceModel>
         9: </configuration>

      如果你的IIS的版本是V6或者V7,你的程序運行將一切正常。但是如果還在使用XP操作系統(tǒng),使用IIS 5.X,會拋出如圖6所示的AddressAlreadyInUseException異常。


      圖6 II 5.x + WsDualHttpBinding導(dǎo)致的AddressAlreadyInUseException異常

       

      該異常的出現(xiàn)和不同版本的IIS監(jiān)聽機制有關(guān)。之所以相同的應(yīng)用在使用基于TCP傳輸?shù)?a title="NetTcpBinding Class" target="_blank" rel="noopener nofollow">NetTcpBinding的時候不會出現(xiàn)問題,那是因為HTTP和TCP它們有一個根本的區(qū)別,TCP本身就是一個雙工模式的傳輸協(xié)議,而HTTP協(xié)議本質(zhì)只能提供單向通信方式。WSDualHttpBinding通過創(chuàng)建兩個單項信道的方式提供雙工通信的實現(xiàn)。

      對于一個雙工通信的WCF服務(wù)來說,回調(diào)過程本質(zhì)上也是一種服務(wù)調(diào)用,是對寄宿于客戶端的回調(diào)服務(wù)的調(diào)用。為了保證回調(diào)的正常運行,在客戶端創(chuàng)建通道的時候(比如上面的代碼通過DuplexChannelFactory的CreateChannel方法的時候),會進(jìn)行回調(diào)服務(wù)的寄宿,并指定回調(diào)服務(wù)的監(jiān)聽地址。在默認(rèn)的情況下該監(jiān)聽地址采用這樣的格式:http://hostname:80/{臨時監(jiān)聽地址}/guid/。

      由于回調(diào)的服務(wù)監(jiān)聽地址采用的默認(rèn)端口是80,在IIS 5.x以及之前的版本中,80端口是IIS獨占的監(jiān)聽端口。所以才會出現(xiàn)AddressAlreadyInUseException異常并提示地址被另外一個應(yīng)用使用,實際上80端口被IIS使用。由于IIS 6和IIS 7采用基于HTTP.SYS驅(qū)動的監(jiān)聽方式實現(xiàn)了端口的共享,故而不會出現(xiàn)上面的問題。關(guān)于不同版本的IIS實現(xiàn)機制,可以參考《WCF技術(shù)剖析(卷1)第7章的有關(guān)IIS服務(wù)寄宿的內(nèi)容。

      由于問題的癥結(jié)在于回調(diào)服務(wù)的監(jiān)聽端口和IIS沖突,所以我們只要能夠解決這種沖突,就能從根本上解決這個問題。由于我們不可以為了解決這個問題把IIS卸掉,或者改變IIS默認(rèn)的端口,所以我們只能改變回調(diào)服務(wù)的地址。WsDualHttpBinding定義了一個ClientBaseAddress使你能很容易地改變回調(diào)服務(wù)的基地址。對于我們給出的案例,我們只要通過下面的配置將clientBaseAddress設(shè)為可用的地址(http://127.0.0.1:8888/ CalculatorService),我們的問題就會迎刃而解。

         1: <?xml version="1.0" encoding="utf-8" ?>
         2: <configuration>
         3:     <system.serviceModel>
         4:         <bindings>
         5:             <wsDualHttpBinding>
         6:                 <binding name="MyBinding" clientBaseAddress="http://127.0.0.1:8888/calculatecallback" />
         7:             </wsDualHttpBinding>
         8:         </bindings>
         9:         <client>
        10:             <endpoint address="http://127.0.0.1:9999/CalculatorService" binding="wsDualHttpBinding"
        11:              bindingConfiguration="MyBinding" contract="Artech.DuplexServices.Contracts.ICalculator"
        12:              name="CalculatorService" />
        13:         </client>
        14:     </system.serviceModel>
        15: </configuration>
      作者:Artech
      出處:http://artech.cnblogs.com/
      本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
      posted @ 2007-03-02 17:17  Artech  閱讀(117947)  評論(269)    收藏  舉報
      主站蜘蛛池模板: 久草热8精品视频在线观看| 无码内射中文字幕岛国片| 国产成人精品亚洲资源| 日韩高清砖码一二区在线| 黑巨人与欧美精品一区| 成人自拍小视频免费观看| 视频一区视频二区在线视频| 亚洲国产高清在线观看视频| 99久久亚洲综合精品成人| 国产不卡精品视频男人的天堂| 一区二区中文字幕久久| 成人福利国产午夜AV免费不卡在线| 内地自拍三级在线观看| 亚洲www永久成人网站| 性欧美牲交在线视频| 久久蜜臀av一区三区| 日韩精品视频一二三四区| 8x国产精品视频| 99久久婷婷国产综合精品青草漫画 | 国产99视频精品免费视频6| 国产精品亚洲av三区色| 亚洲熟女精品一区二区| 老熟妇高潮一区二区三区| 国产精品入口麻豆| 天堂av在线一区二区| 国产偷国产偷亚洲高清日韩| 国产精品福利一区二区久久| 国产免费高清69式视频在线观看| 国内精品卡一卡二卡三| 久热中文字幕在线精品观| 欧美日产国产精品日产| 国产成人综合色就色综合| 松潘县| 精品一日韩美女性夜视频| 欧美videosdesexo吹潮| 国产尤物精品自在拍视频首页| 少妇人妻av毛片在线看| 亚洲AV无码国产永久播放蜜芽| 少妇宾馆粉嫩10p| 在线亚洲人成电影网站色www| 国产99青青成人A在线|