青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

路漫漫,長修遠(yuǎn),我們不能沒有錢
隨筆 - 173, 文章 - 0, 評(píng)論 - 257, 引用 - 0
數(shù)據(jù)加載中……

boost中asio網(wǎng)絡(luò)庫多線程并發(fā)處理實(shí)現(xiàn),以及asio在多線程模型中線程的調(diào)度情況和線程安全。 (轉(zhuǎn)載)

轉(zhuǎn)載自(http://www.cnblogs.com/lidabo/p/3906055.html)


1、實(shí)現(xiàn)多線程方法:

    其實(shí)就是多個(gè)線程同時(shí)調(diào)用io_service::run

1         for (int i = 0; i != m_nThreads; ++i)
2         {
3             boost::shared_ptr<boost::thread> pTh(new boost::thread(
4                 boost::bind(&boost::asio::io_service::run,&m_ioService)));
5             m_listThread.push_back(pTh);
6         }


2、多線程調(diào)度情況:

    asio規(guī)定:只能在調(diào)用io_service::run的線程中才能調(diào)用事件完成處理器。


注:事件完成處理器就是你async_accept、async_write等注冊(cè)的句柄,類似于回調(diào)的東西。


單線程:

    如果只有一個(gè)線程調(diào)用io_service::run,根據(jù)asio的規(guī)定,事件完成處理器也只能在這個(gè)線程中執(zhí)行。也就是說,你所有代碼都在同一個(gè)線程中運(yùn)行,因此變量的訪問是安全的。


多線程:

    如果有多個(gè)線程同時(shí)調(diào)用io_service::run以實(shí)現(xiàn)多線程并發(fā)處理。對(duì)于asio來說,這些線程都是平等的,沒有主次之分。如果你投遞的一個(gè)請(qǐng)求比如async_write完成時(shí),asio將隨機(jī)的激活調(diào)用io_service::run的線程。并在這個(gè)線程中調(diào)用事件完成處理器(async_write當(dāng)時(shí)注冊(cè)的句柄)。如果你的代碼耗時(shí)較長,這個(gè)時(shí)候你投遞的另一個(gè)async_write請(qǐng)求完成時(shí),asio將不等待你的代碼處理完成,它將在另外的一個(gè)調(diào)用io_service::run線程中,調(diào)用async_write當(dāng)時(shí)注冊(cè)的句柄。也就是說,你注冊(cè)的事件完成處理器有可能同時(shí)在多個(gè)線程中調(diào)用。


當(dāng)然你可以使用 boost::asio::io_service::strand讓完成事件處理器的調(diào)用,在同一時(shí)間只有一個(gè), 比如下面的的代碼:

  socket_.async_read_some(boost::asio::buffer(buffer_),
      strand_.wrap(
        boost::bind(&connection::handle_read, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred)));

...

boost::asio::io_service::strand strand_;

 

    此時(shí)async_read_som完成后掉用handle_read時(shí),必須等待其它handle_read調(diào)用完成時(shí)才能被執(zhí)行(async_read_som引起的handle_read調(diào)用)。

    多線程調(diào)用時(shí),還有一個(gè)重要的問題,那就是無序化。比如說,你短時(shí)間內(nèi)投遞多個(gè)async_write,那么完成處理器的調(diào)用并不是按照你投遞async_write的順序調(diào)用的。asio第一次調(diào)用完成事件處理器,有可能是第二次async_write返回的結(jié)果,也有可能是第3次的。使用strand也是這樣的。strand只是保證同一時(shí)間只運(yùn)行一個(gè)完成處理器,但它并不保證順序。

 


 

代碼測(cè)試:

服務(wù)器:

將下面的代碼編譯以后,使用cmd命令提示符下傳人參數(shù)<IP> <port> <threads>調(diào)用

比如:test.exe 0.0.0.0 3005 10   

客服端 使用windows自帶的telnet

cmd命令提示符:

telnet 127.0.0.1 3005

 

原理:客戶端連接成功后,同一時(shí)間調(diào)用100次boost::asio::async_write給客戶端發(fā)送數(shù)據(jù),并且在完成事件處理器中打印調(diào)用序號(hào),和線程ID。

核心代碼:


 1     void start()
 2     {
 3         for (int i = 0; i != 100; ++i)
 4         {
 5             boost::shared_ptr<string> pStr(new string);
 6             *pStr = boost::lexical_cast<string>(boost::this_thread::get_id());
 7             *pStr += "\r\n";
 8             boost::asio::async_write(m_nSocket,boost::asio::buffer(*pStr),
 9                 boost::bind(&CMyTcpConnection::HandleWrite,shared_from_this(),
10                  boost::asio::placeholders::error,
11                  boost::asio::placeholders::bytes_transferred,
12                  pStr,i)
13                 );
14         }
15     }
16 
17 //去掉 boost::mutex::scoped_lock lock(m_ioMutex); 效果更明顯。
18 
19     void HandleWrite(const boost::system::error_code& error
20         ,std::size_t bytes_transferred
21         ,boost::shared_ptr<string> pStr,int nIndex)
22     {
23         if (!error)
24         {
25             boost::mutex::scoped_lock lock(m_ioMutex);
26             cout << "發(fā)送序號(hào)=" << nIndex << ",線程id=" << boost::this_thread::get_id() << endl;
27         }
28         else
29         {
30             cout << "連接斷開" << endl;
31         }
32     }


完整代碼:

  1 #include <boost/bind.hpp>
  2 #include <boost/shared_ptr.hpp>
  3 #include <boost/enable_shared_from_this.hpp>
  4 #include <boost/asio.hpp>
  5 #include <boost/lexical_cast.hpp>
  6 #include <boost/thread.hpp>
  7 #include <boost/thread/mutex.hpp>
  8 #include <string>
  9 #include <iostream>
 10 
 11 
 12 using std::cout;
 13 using std::endl;
 14 using std::string;
 15 using boost::asio::ip::tcp;
 16 
 17 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 18 
 19 
 20 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 21 
 22 class CMyTcpConnection : public boost::enable_shared_from_this<CMyTcpConnection>
 23 {
 24 public:
 25     CMyTcpConnection(boost::asio::io_service &ser)
 26         :m_nSocket(ser)
 27     {
 28     }
 29 
 30     typedef boost::shared_ptr<CMyTcpConnection> CPMyTcpCon;
 31 
 32 
 33     static CPMyTcpCon CreateNew(boost::asio::io_service& io_service) {
 34         return CPMyTcpCon(new CMyTcpConnection(io_service));
 35     }
 36 
 37 
 38    
 39 public:
 40     void start()
 41     {
 42         for (int i = 0; i != 100; ++i) {
 43             boost::shared_ptr<string> pStr(new string);
 44             *pStr = boost::lexical_cast<string>(boost::this_thread::get_id());
 45             *pStr += "\r\n";
 46             boost::asio::async_write(m_nSocket,boost::asio::buffer(*pStr),
 47                 boost::bind(&CMyTcpConnection::HandleWrite,shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, pStr,i)
 48                 );
 49         }
 50     }
 51 
 52 
 53     tcp::socket& socket()
 54     {
 55         return m_nSocket;
 56     }
 57 
 58 
 59 private:
 60     void HandleWrite(const boost::system::error_code& error ,std::size_t bytes_transferred ,boost::shared_ptr<string> pStr,int nIndex)
 61     {
 62         if (!error) {
 63             boost::mutex::scoped_lock lock(m_ioMutex);
 64             cout << "發(fā)送序號(hào)=" << nIndex << ",線程id=" << boost::this_thread::get_id() << endl;
 65         } else {
 66             cout << "連接斷開" << endl;
 67         }
 68     }
 69 
 70 public:
 71 
 72 private:
 73     tcp::socket m_nSocket;
 74     boost::mutex m_ioMutex;
 75 };
 76 
 77 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 78 
 79 
 80 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 81 
 82 class CMyService : private boost::noncopyable
 83 {
 84 public:
 85     CMyService(string const &strIP,string const &strPort,int nThreads)
 86         :m_tcpAcceptor(m_ioService)
 87         ,m_nThreads(nThreads)
 88     {
 89         tcp::resolver resolver(m_ioService);
 90         tcp::resolver::query query(strIP,strPort);
 91         tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
 92         boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
 93         m_tcpAcceptor.open(endpoint.protocol());
 94         m_tcpAcceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
 95         m_tcpAcceptor.bind(endpoint);
 96         m_tcpAcceptor.listen();
 97 
 98 
 99         StartAccept();
100     }
101 
102     ~CMyService(){Stop();}
103 
104 public:
105     void Stop() 
106     { 
107         m_ioService.stop();
108         for (std::vector<boost::shared_ptr<boost::thread>>::const_iterator it = m_listThread.cbegin();
109             it != m_listThread.cend(); ++ it)
110         {
111             (*it)->join();
112         }
113     }
114     void Start() {
115         for (int i = 0; i != m_nThreads; ++i) {
116             boost::shared_ptr<boost::thread> pTh( new boost::thread( boost::bind(&boost::asio::io_service::run, &m_ioService) ) );
117             m_listThread.push_back(pTh);
118         }
119     }
120 private:
121     void HandleAccept(const boost::system::error_code& error ,boost::shared_ptr<CMyTcpConnection> newConnect)
122     {
123         if (!error) {
124             newConnect->start();
125         }
126         StartAccept();
127     }
128 
129 
130     void StartAccept()
131     {
132         CMyTcpConnection::CPMyTcpCon newConnect = CMyTcpConnection::CreateNew(m_tcpAcceptor.get_io_service());
133         m_tcpAcceptor.async_accept( newConnect->socket(), vboost::bind(&CMyService::HandleAccept, this, boost::asio::placeholders::error, newConnect) );
134     }
135 
136 
137 private:
138     boost::asio::io_service m_ioService;
139     boost::asio::ip::tcp::acceptor m_tcpAcceptor;
140     std::vector<boost::shared_ptr<boost::thread>> m_listThread;
141     std::size_t m_nThreads;
142 };
143 
144 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
145 
146 
147 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
148 
149 int main(int argc, char* argv[])
150 {
151     try
152     {
153         if (argc != 4)
154         {
155             std::cerr << "<IP> <port> <threads>\n";
156             return 1;
157         }
158         int nThreads = boost::lexical_cast<int>(argv[3]);
159         CMyService mySer(argv[1], argv[2], nThreads);
160         mySer.Start();
161         getchar();
162         mySer.Stop();
163     } catch (std::exception& e) {
164         std::cerr << "Exception: " << e.what() << "\n";
165     }
166     return 0;
167 }



## 相關(guān)函數(shù)介紹

### boost::asio::ip::tcp::resolver

iterator resolve(
    const endpoint_type & e,
    boost::system::error_code & ec);
Return Value

A forward-only iterator that can be used to traverse the list of endpoint entries. Returns a default constructed iterator if an error occurs.

Remarks

A default constructed iterator represents the end of the list.

A successful call to this function is guaranteed to return at least one entry.


tcp::resolver一般和tcp::resolver::query結(jié)合用,通過query這個(gè)詞顧名思義就知道它是用來查詢socket的相應(yīng)信息,一般而言我們關(guān)心socket的東東有address,port而已,通過 tcp::resolver很容易實(shí)現(xiàn)設(shè)置和查詢,它通過query把字符串格式的ip如192.168.0.200或主機(jī)名 http://localhost,端口“8080”等轉(zhuǎn)化成socket內(nèi)部表示格式,這樣我們應(yīng)用的時(shí)候可以直接使用字符串的形式,而且不用再擔(dān)心 socket的字節(jié)順序轉(zhuǎn)化問題。示例如下:


1     boost::asio::io_service io_service ;  
2     boost::asio::ip::tcp::resolver resolver(io_service);  
3     boost::asio::ip::tcp::resolver::query query("localhost""9000");

還 有要說明的是, boost::asio把通訊雙方(server, client)都用endpoint的表示,所以endpoint中的address, port 分別封裝了ip和端口。貌似resolver和endpoint不相干,于是乎出現(xiàn)tcp::resolver::iterator了,它是 resolver的迭代器,其實(shí)就是endpoint的指針,那么就可以這樣:
 1     boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);  
 2     boost::asio::ip::tcp::resolver::iterator end;     //默認(rèn)構(gòu)造的resolver::iterator,用來代表失敗
 3     boost::system::error_code error = boost::asio::error::host_not_found;  
 4     boost::asio::ip::tcp::endpoint endpoint;  
 5     while (error && endpoint_iterator != end) {  
 6         endpoint = *endpoint_iterator ;    //返回的是迭代器,需要解引用成endpoint
 7         socket.close();    //先close,再connect
 8         socket.connect(endpoint, error);  
 9         endpoint_iterator++ ;  
10     } 

得到endpoint后就好說啦,endpoint.address().to_string()就能夠返回string格式的ip地址,endpoint.port()返回端口。

其實(shí)endpoint 完全可以自己構(gòu)造,方法也是很簡(jiǎn)單的,tcp::endpoint(tcp::v4(), (unsigned short)9000) 這個(gè)是server端的用法,tcp::v4()直接返回自己的address,如果用于client那么需要設(shè)置server的ip ,實(shí)現(xiàn)如下:

1 
2     boost::system::error_code error = boost::asio::error::host_not_found;  
3     boost::asio::ip::address add;  
4     add.from_string("127.0.0.1");  
5     tcp::endpoint endpoint(add, short(9000));  
6     socket.connect(endpoint, error);  
7 

這樣不使用resolver也是可以的。
還有更神奇的:

 1 
 2     boost::asio::io_service ioservice ;  
 3     boost::asio::io_service my_io_service ;  
 4     boost::asio::ip::tcp::resolver resolver(my_io_service);  
 5     boost::asio::ip::tcp::resolver::query query("www.google.com""http");  
 6     boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query);  
 7     boost::asio::ip::tcp::resolver::iterator end; // End marker.  
 8       
 9     while (iter != end) {  
10       boost::asio::ip::tcp::endpoint endpoint = *iter++;  
11       std::cout << endpoint << std::endl;  
12     }  
13 


這樣有發(fā)現(xiàn)一個(gè)新的用途,通過resolver迭代可以得到多個(gè)節(jié)點(diǎn)endpoint,比如google 就有好幾個(gè)ip。
上面這個(gè)例子的運(yùn)行結(jié)果:

1         74.125.128.106:80  
2         74.125.128.147:80  
3         74.125.128.99:80  
4         74.125.128.103:80  
5         74.125.128.104:80  
6         74.125.128.105:80




### boost::mutex::scoped_lock

boost::mutex::scoped_lock lock(m_ioMutex);

其依賴RAII機(jī)制, 在過了作用域之后對(duì)鎖進(jìn)行自動(dòng)釋放和回收.其實(shí)現(xiàn)代碼如圖所示

boost_1_60_0/boost/asio/detail/scoped_lock.hpp:

  1 //
  2 // detail/scoped_lock.hpp
  3 // ~~~~~~~~~~~~~~~~~~~~~~
  4 //
  5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6 //
  7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9 //
 10 
 11 #ifndef BOOST_ASIO_DETAIL_SCOPED_LOCK_HPP
 12 #define BOOST_ASIO_DETAIL_SCOPED_LOCK_HPP
 13 
 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
 15 # pragma once
 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 17 
 18 #include <boost/asio/detail/noncopyable.hpp>
 19 
 20 #include <boost/asio/detail/push_options.hpp>
 21 
 22 namespace boost {
 23 namespace asio {
 24 namespace detail {
 25 
 26 // Helper class to lock and unlock a mutex automatically.
 27 template <typename Mutex>
 28 class scoped_lock
 29   : private noncopyable
 30 {
 31 public:
 32   // Tag type used to distinguish constructors.
 33   enum adopt_lock_t { adopt_lock };
 34 
 35   // Constructor adopts a lock that is already held.
 36   scoped_lock(Mutex& m, adopt_lock_t)
 37     : mutex_(m),
 38       locked_(true)
 39   {
 40   }
 41 
 42   // Constructor acquires the lock.
 43   explicit scoped_lock(Mutex& m)
 44     : mutex_(m)
 45   {
 46     mutex_.lock();
 47     locked_ = true;
 48   }
 49 
 50   // Destructor releases the lock.
 51   ~scoped_lock()
 52   {
 53     if (locked_)
 54       mutex_.unlock();
 55   }
 56 
 57   // Explicitly acquire the lock.
 58   void lock()
 59   {
 60     if (!locked_)
 61     {
 62       mutex_.lock();
 63       locked_ = true;
 64     }
 65   }
 66 
 67   // Explicitly release the lock.
 68   void unlock()
 69   {
 70     if (locked_)
 71     {
 72       mutex_.unlock();
 73       locked_ = false;
 74     }
 75   }
 76 
 77   // Test whether the lock is held.
 78   bool locked() const
 79   {
 80     return locked_;
 81   }
 82 
 83   // Get the underlying mutex.
 84   Mutex& mutex()
 85   {
 86     return mutex_;
 87   }
 88 
 89 private:
 90   // The underlying mutex.
 91   Mutex& mutex_;
 92 
 93   // Whether the mutex is currently locked or unlocked.
 94   bool locked_;
 95 };
 96 
 97 // namespace detail
 98 // namespace asio
 99 // namespace boost
100 
101 #include <boost/asio/detail/pop_options.hpp>
102 
103 #endif // BOOST_ASIO_DETAIL_SCOPED_LOCK_HPP
104 


### lexical_cast

lexical_cast是boost中一個(gè)非常有用,常用,好用的庫,我現(xiàn)在的小數(shù)據(jù)轉(zhuǎn)換用的都是lexical_cast。
lexical_cast最大的特點(diǎn)是安全,包括長度安全,類型安全。

使用方式:

1 #include <boost/lexical_cast.hpp> 
2 
3 const double PI=3.1415926535;
4 string str;
5 str = lexical_cast<string>(PI); 
6 
7 string str="3.1415926535";
8 double PI=lexical_cast<double>(str); 
9 

如果轉(zhuǎn)換失敗, 拋出bad_lexical_cast異常

其實(shí)現(xiàn)方式如下:

boost_1_60_0/boost/lexical_cast.hpp

  1 // Copyright Kevlin Henney, 2000-2005.
  2 // Copyright Alexander Nasonov, 2006-2010.
  3 // Copyright Antony Polukhin, 2011-2014.
  4 //
  5 // Distributed under the Boost Software License, Version 1.0. (See
  6 // accompanying file LICENSE_1_0.txt or copy at
  7 // http://www.boost.org/LICENSE_1_0.txt)
  8 //
  9 // what:  lexical_cast custom keyword cast
 10 // who:   contributed by Kevlin Henney,
 11 //        enhanced with contributions from Terje Slettebo,
 12 //        with additional fixes and suggestions from Gennaro Prota,
 13 //        Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
 14 //        Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
 15 //        Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
 16 // when:  November 2000, March 2003, June 2005, June 2006, March 2011 - 2014
 17 
 18 #ifndef BOOST_LEXICAL_CAST_INCLUDED
 19 #define BOOST_LEXICAL_CAST_INCLUDED
 20 
 21 #include <boost/config.hpp>
 22 #ifdef BOOST_HAS_PRAGMA_ONCE
 23 #   pragma once
 24 #endif
 25 
 26 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
 27 #define BOOST_LCAST_NO_WCHAR_T
 28 #endif
 29 
 30 #include <boost/range/iterator_range_core.hpp>
 31 #include <boost/lexical_cast/bad_lexical_cast.hpp>
 32 #include <boost/lexical_cast/try_lexical_convert.hpp>
 33 
 34 namespace boost 
 35 {
 36     template <typename Target, typename Source>
 37     inline Target lexical_cast(const Source &arg)
 38     {
 39         Target result;
 40 
 41         if (!boost::conversion::detail::try_lexical_convert(arg, result)) {
 42             boost::conversion::detail::throw_bad_cast<Source, Target>();
 43         }
 44 
 45         return result;
 46     }
 47 
 48     template <typename Target>
 49     inline Target lexical_cast(const char* chars, std::size_t count)
 50     {
 51         return ::boost::lexical_cast<Target>(
 52             ::boost::iterator_range<const char*>(chars, chars + count)
 53         );
 54     }
 55 
 56     template <typename Target>
 57     inline Target lexical_cast(const unsigned char* chars, std::size_t count)
 58     {
 59         return ::boost::lexical_cast<Target>(
 60             ::boost::iterator_range<const unsigned char*>(chars, chars + count)
 61         );
 62     }
 63 
 64     template <typename Target>
 65     inline Target lexical_cast(const signed char* chars, std::size_t count)
 66     {
 67         return ::boost::lexical_cast<Target>(
 68             ::boost::iterator_range<const signed char*>(chars, chars + count)
 69         );
 70     }
 71 
 72 #ifndef BOOST_LCAST_NO_WCHAR_T
 73     template <typename Target>
 74     inline Target lexical_cast(const wchar_t* chars, std::size_t count)
 75     {
 76         return ::boost::lexical_cast<Target>(
 77             ::boost::iterator_range<const wchar_t*>(chars, chars + count)
 78         );
 79     }
 80 #endif
 81 #ifndef BOOST_NO_CXX11_CHAR16_T
 82     template <typename Target>
 83     inline Target lexical_cast(const char16_t* chars, std::size_t count)
 84     {
 85         return ::boost::lexical_cast<Target>(
 86             ::boost::iterator_range<const char16_t*>(chars, chars + count)
 87         );
 88     }
 89 #endif
 90 #ifndef BOOST_NO_CXX11_CHAR32_T
 91     template <typename Target>
 92     inline Target lexical_cast(const char32_t* chars, std::size_t count)
 93     {
 94         return ::boost::lexical_cast<Target>(
 95             ::boost::iterator_range<const char32_t*>(chars, chars + count)
 96         );
 97     }
 98 #endif
 99 
100 // namespace boost
101 
102 #undef BOOST_LCAST_NO_WCHAR_T
103 
104 #endif // BOOST_LEXICAL_CAST_INCLUDED
105 
106 



posted on 2017-10-14 11:44 Khan 閱讀(1831) 評(píng)論(0)  編輯 收藏 引用 所屬分類: GCC/G++跨平臺(tái)開發(fā)

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            精品成人在线观看| 亚洲视频免费在线观看| 久久久综合免费视频| 中文av一区特黄| 亚洲欧美日韩视频一区| 一本久道综合久久精品| 亚洲午夜久久久| 亚洲一区二区少妇| 亚洲女同同性videoxma| 久久精品在线播放| 麻豆精品网站| 欧美图区在线视频| 国产亚洲一区二区在线观看 | 欧美国产日韩一区二区三区| 欧美日本免费| 国产精品一区在线观看| 国产综合自拍| 亚洲精品国产视频| 午夜精品福利一区二区蜜股av| 欧美在线资源| 亚洲高清视频中文字幕| 亚洲国产欧美久久| 亚洲欧美日韩国产| 欧美va亚洲va日韩∨a综合色| 欧美体内she精视频在线观看| 一区二区三区在线观看国产| 正在播放欧美视频| 女女同性女同一区二区三区91| 亚洲精品国产精品国产自| 欧美一级大片在线免费观看| 欧美一区二区黄色| 一本久久知道综合久久| 羞羞色国产精品| 亚洲成人在线免费| 欧美尤物一区| 亚洲国产精品成人综合| 亚洲免费在线播放| 欧美日本在线| 亚洲缚视频在线观看| 亚洲大片免费看| 亚洲一区二区三区高清 | 一区二区三区国产在线| 香蕉乱码成人久久天堂爱免费 | 国产香蕉久久精品综合网| 亚洲区一区二区三区| 久久精品一区二区三区不卡| 9国产精品视频| 女同一区二区| 亚洲国产精品成人精品| 亚洲日本黄色| 一区二区精品| 欧美激情亚洲一区| 亚洲高清网站| 欧美大片91| 久久久亚洲午夜电影| 国产亚洲精品久久飘花| 欧美一区二区三区男人的天堂| 亚洲乱码国产乱码精品精可以看| 久久婷婷亚洲| 亚洲国产高清在线观看视频| 裸体一区二区| 久久综合一区二区| 在线观看视频一区二区| 久久婷婷久久一区二区三区| 性欧美暴力猛交69hd| 国产日韩欧美综合一区| 久久精品99| 久久久欧美精品sm网站| 尤物yw午夜国产精品视频明星| 久久久久久久久蜜桃| 先锋影音一区二区三区| 国产一区二区三区久久久| 久久久久久91香蕉国产| 久久久久久夜| 亚洲人成啪啪网站| 亚洲二区视频在线| 欧美福利在线观看| 亚洲私人影院| 亚洲专区在线| 狠狠色狠狠色综合人人| 欧美福利视频| 欧美日韩三区四区| 亚洲女人天堂成人av在线| 国产精品美女久久久免费| 欧美一级欧美一级在线播放| 欧美一区二区在线免费播放| 亚洲国产午夜| 这里只有精品在线播放| 国产一区日韩二区欧美三区| 欧美福利视频| 国产精品免费观看在线| 蜜桃久久精品一区二区| 欧美久久久久久久| 欧美性淫爽ww久久久久无| 欧美一区二区网站| 久久亚洲精选| 亚洲午夜性刺激影院| 性色一区二区| 亚洲人成网站色ww在线| 亚洲最新在线视频| 国产真实精品久久二三区| 亚洲人成网在线播放| 国产日韩亚洲| 一区二区不卡在线视频 午夜欧美不卡在 | 国产精品永久免费| 欧美不卡高清| 欧美精品日韩| 亚洲欧美日韩精品久久久久| 国内精品久久久久久久影视蜜臀| 欧美国产三区| 国产日韩精品一区二区三区在线| 免费中文日韩| 国产精品毛片a∨一区二区三区|国 | 欧美性视频网站| 欧美电影在线| 国产日韩av高清| 日韩午夜av电影| 亚洲国语精品自产拍在线观看| 一区二区三区毛片| 99国产麻豆精品| 久久久久久色| 久久久久久**毛片大全| 国产精品久久影院| 亚洲黄色av| 永久免费视频成人| 午夜精品久久久久久久久| 亚洲主播在线| 欧美日韩一级黄| 亚洲精品乱码视频| 亚洲人成网站在线观看播放| 久久久综合香蕉尹人综合网| 久久久久青草大香线综合精品| 国产精品午夜在线观看| 亚洲在线日韩| 久久都是精品| 国产在线精品二区| 久久av在线| 牛牛国产精品| 亚洲国产天堂久久综合| 欧美成人69| 亚洲精品精选| 亚洲性线免费观看视频成熟| 99热免费精品在线观看| 亚洲破处大片| 欧美精品久久天天躁| 亚洲国产另类 国产精品国产免费| 一区久久精品| 你懂的成人av| 亚洲激情成人网| 一区二区三区精品久久久| 欧美三级电影大全| 亚洲视频第一页| 午夜免费在线观看精品视频| 国产精品美女久久久久久久| 亚洲欧美精品一区| 久久影视三级福利片| 精品88久久久久88久久久| 免费精品视频| 在线视频日韩| 久久欧美肥婆一二区| 91久久久久久国产精品| 欧美激情偷拍| 亚洲欧美日韩在线播放| 久久综合狠狠综合久久激情| 亚洲国产精品成人综合色在线婷婷| 蜜桃av一区| 亚洲一区bb| 欧美成人一区二区| 亚洲一级免费视频| 国产中文一区二区| 欧美理论电影在线观看| 亚洲欧美中文另类| 亚洲成色最大综合在线| 亚洲欧美日韩电影| 精品成人一区二区三区| 欧美日韩另类视频| 久久精品二区| 亚洲美女视频在线免费观看| 久久久99国产精品免费| 亚洲视频在线观看三级| 极品尤物av久久免费看| 国产精品久久国产精麻豆99网站| 久久精品国产v日韩v亚洲| 亚洲美女黄色| 免费在线成人av| 午夜日韩电影| 一本色道久久99精品综合| 国产日韩欧美日韩| 欧美日韩中文在线| 免费黄网站欧美| 欧美一区二区三区视频免费| 亚洲国产一区视频| 麻豆久久久9性大片| 欧美一区高清| 亚洲午夜未删减在线观看| 亚洲精品免费观看| 亚洲福利视频一区二区| 国产自产精品| 国产精品系列在线| 国产精品每日更新|