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

陳碩的Blog

Muduo 網(wǎng)絡(luò)編程示例之三:定時(shí)器

陳碩 (giantchen_AT_gmail)

Blog.csdn.net/Solstice

這是《Muduo 網(wǎng)絡(luò)編程示例》系列的第三篇文章。

Muduo 全系列文章列表: http://blog.csdn.net/Solstice/category/779646.aspx

 

程序中的時(shí)間

程序中對(duì)時(shí)間的處理是個(gè)大問(wèn)題,我打算單獨(dú)寫一篇文章來(lái)全面地討論這個(gè)問(wèn)題。文章暫定名《〈程序中的日期與時(shí)間〉第二章 計(jì)時(shí)與定時(shí)》,跟《〈程序中的日期與時(shí)間〉第一章 日期計(jì)算》放到一個(gè)系列,這個(gè)系列預(yù)計(jì)會(huì)有四篇文章。

在這篇博客里里我先簡(jiǎn)要談?wù)勁c編程直接相關(guān)的內(nèi)容,把更深入的內(nèi)容留給上面提到的日期與時(shí)間專題文章。

在一般的服務(wù)端程序設(shè)計(jì)中,與時(shí)間有關(guān)的常見(jiàn)任務(wù)有:

  1. 獲取當(dāng)前時(shí)間,計(jì)算時(shí)間間隔;
  2. 時(shí)區(qū)轉(zhuǎn)換與日期計(jì)算;把紐約當(dāng)?shù)貢r(shí)間轉(zhuǎn)換為上海當(dāng)?shù)貢r(shí)間;2011-02-05 之后第 100 天是幾月幾號(hào)星期幾?等等
  3. 定時(shí)操作,比如在預(yù)定的時(shí)間執(zhí)行一項(xiàng)任務(wù),或者在一段延時(shí)之后執(zhí)行一項(xiàng)任務(wù)。

其中第 2 項(xiàng)看起來(lái)復(fù)雜,其實(shí)最簡(jiǎn)單。日期計(jì)算用 Julian Day Number,時(shí)區(qū)轉(zhuǎn)換用 tz database;惟一麻煩一點(diǎn)的是夏令時(shí),但也可以用 tz database 解決。這些操作都是純函數(shù),很容易用一套單元測(cè)試來(lái)驗(yàn)證代碼的正確性。需要特別注意的是,用 tzset/localtime_r 來(lái)做時(shí)區(qū)轉(zhuǎn)換在多線程環(huán)境下可能會(huì)有問(wèn)題;對(duì)此我的解決辦法是寫一個(gè) TimeZone class,以避免影響全局,將來(lái)在日期與時(shí)間專題中會(huì)講到。以下本文不考慮時(shí)區(qū),均為 UTC 時(shí)間。

真正麻煩的是第 1 項(xiàng)和第 3 項(xiàng)。一方面,Linux 有一大把令人眼花繚亂的與時(shí)間相關(guān)的函數(shù)和結(jié)構(gòu)體,在程序中該如何選用?另一方面,計(jì)算機(jī)中的時(shí)鐘不是理想的計(jì)時(shí)器,它可能會(huì)漂移或跳變;最后,民用的 UTC 時(shí)間與閏秒的關(guān)系也讓定時(shí)任務(wù)變得復(fù)雜和微妙。當(dāng)然,與系統(tǒng)當(dāng)前時(shí)間有關(guān)的操作也讓單元測(cè)試變得困難。

Linux 時(shí)間函數(shù)

Linux 的計(jì)時(shí)函數(shù),用于獲得當(dāng)前時(shí)間:

  • time(2) / time_t (秒)
  • ftime(3) / struct timeb (毫秒)
  • gettimeofday(2) / struct timeval (微秒)
  • clock_gettime(2) / struct timespec (納秒)
  • gmtime / localtime / timegm / mktime / strftime / struct tm (這些與當(dāng)前時(shí)間無(wú)關(guān))

定時(shí)函數(shù),用于讓程序等待一段時(shí)間或安排計(jì)劃任務(wù):

  • sleep
  • alarm
  • usleep
  • nanosleep
  • clock_nanosleep
  • getitimer / setitimer
  • timer_create / timer_settime / timer_gettime / timer_delete
  • timerfd_create / timerfd_gettime / timerfd_settime

我的取舍如下:

  • (計(jì)時(shí))只使用 gettimeofday 來(lái)獲取當(dāng)前時(shí)間。
  • (定時(shí))只使用 timerfd_* 系列函數(shù)來(lái)處理定時(shí)。

gettimeofday 入選原因:(這也是 muduo::Timestamp class 的主要設(shè)計(jì)考慮)

  1. time 的精度太低,ftime 已被廢棄,clock_gettime 精度最高,但是它系統(tǒng)調(diào)用的開(kāi)銷比 gettimeofday 大。
  2. 在 x86-64 平臺(tái)上,gettimeofday 不是系統(tǒng)調(diào)用,而是在用戶態(tài)實(shí)現(xiàn)的(搜 vsyscall),沒(méi)有上下文切換和陷入內(nèi)核的開(kāi)銷。
  3. gettimeofday 的分辨率 (resolution) 是 1 微秒,足以滿足日常計(jì)時(shí)的需要。muduo::Timestamp 用一個(gè) int64_t 來(lái)表示從 Epoch 到現(xiàn)在的微秒數(shù),其范圍可達(dá)上下 30 萬(wàn)年。

timerfd_* 入選的原因:

  1. sleep / alarm / usleep 在實(shí)現(xiàn)時(shí)有可能用了信號(hào) SIGALRM,在多線程程序中處理信號(hào)是個(gè)相當(dāng)麻煩的事情,應(yīng)當(dāng)盡量避免。(近期我會(huì)寫一篇博客仔細(xì)講講“多線程、RAII、fork() 與信號(hào)”)
  2. nanosleep 和 nanosleep 是線程安全的,但是在非阻塞網(wǎng)絡(luò)編程中,絕對(duì)不能用讓線程掛起的方式來(lái)等待一段時(shí)間,程序會(huì)失去響應(yīng)。正確的做法是注冊(cè)一個(gè)時(shí)間回調(diào)函數(shù)。
  3. getitimer 和 timer_create 也是用信號(hào)來(lái) deliver 超時(shí),在多線程程序中也會(huì)有麻煩。timer_create 可以指定信號(hào)的接收方是進(jìn)程還是線程,算是一個(gè)進(jìn)步,不過(guò)在信號(hào)處理函數(shù)(signal handler)能做的事情實(shí)在很受限。
  4. timerfd_create 把時(shí)間變成了一個(gè)文件描述符,該“文件”在定時(shí)器超時(shí)的那一刻變得可讀,這樣就能很方便地融入到 select/poll 框架中,用統(tǒng)一的方式來(lái)處理 IO 事件和超時(shí)事件,這也正是 Reactor 模式的長(zhǎng)處。我在一年前發(fā)表的《Linux 新增系統(tǒng)調(diào)用的啟示》中也談到這個(gè)想法,現(xiàn)在我把這個(gè)想法在 muduo 網(wǎng)絡(luò)庫(kù)中實(shí)現(xiàn)了。
  5. 傳統(tǒng)的 Reactor 利用 select/poll/epoll 的 timeout 來(lái)實(shí)現(xiàn)定時(shí)功能,但 poll 和 epoll 的定時(shí)精度只有毫秒,遠(yuǎn)低于 timerfd_settime 的定時(shí)精度。

必須要說(shuō)明,在 Linux 這種非實(shí)時(shí)多任務(wù)操作系統(tǒng)中,在用戶態(tài)實(shí)現(xiàn)完全精確可控的計(jì)時(shí)和定時(shí)是做不到的,因?yàn)楫?dāng)前任務(wù)可能會(huì)被隨時(shí)切換出去,這在 CPU 負(fù)載大的時(shí)候尤為明顯。但是,我們的程序可以盡量提高時(shí)間精度,必要的時(shí)候通過(guò)控制 CPU 負(fù)載來(lái)提高時(shí)間操作的可靠性,在程序在 99.99% 的時(shí)候都是按預(yù)期執(zhí)行的。這或許比換用實(shí)時(shí)操作系統(tǒng)并重新編寫并測(cè)試代碼要經(jīng)濟(jì)一些。

關(guān)于時(shí)間的精度(accuracy)問(wèn)題我留到專題博客文章中討論,它與分辨率(resolution)不完全是一回事兒。時(shí)間跳變和閏秒的影響與應(yīng)對(duì)也不在此處展開(kāi)討論了。

Muduo 的定時(shí)器接口

Muduo EventLoop 有三個(gè)定時(shí)器函數(shù):

   1: typedef boost::function<void()> TimerCallback;
   2:  
   3: ///
   4: /// Reactor, at most one per thread.
   5: ///
   6: /// This is an interface class, so don't expose too much details.
   7: class EventLoop : boost::noncopyable
   8: {
   9:  public:
  10:   // ...
  11:  
  12:   // timers
  13:  
  14:   ///
  15:   TimerId runAt(const Timestamp& time, const TimerCallback& cb);
  16:  
  17:   ///
  18:   /// Runs callback after @c delay seconds.
  19:   /// Safe to call from other threads.
  20:   TimerId runAfter(double delay, const TimerCallback& cb);
  21:  
  22:   ///
  23:   /// Runs callback every @c interval seconds.
  24:   /// Safe to call from other threads.
  25:   TimerId runEvery(double interval, const TimerCallback& cb);
  26:  
  27:   /// Cancels the timer.
  28:   /// Safe to call from other threads.
  29:   // void cancel(TimerId timerId);
  30:  
  31:   // ...
  32: };
  • runAt 在指定的時(shí)間調(diào)用 TimerCallback
  • runAfter 等一段時(shí)間調(diào)用 TimerCallback
  • runEvery 以固定的間隔反復(fù)調(diào)用 TimerCallback
  • cancel 取消 timer,目前未實(shí)現(xiàn)

回調(diào)函數(shù)在 EventLoop 對(duì)象所在的線程發(fā)生,與 onMessage() onConnection() 等網(wǎng)絡(luò)事件函數(shù)在同一個(gè)線程。

Muduo 的 TimerQueue 采用了最簡(jiǎn)單的實(shí)現(xiàn)(鏈表)來(lái)管理定時(shí)器,它的效率比不上常見(jiàn)的 binary heap 的做法,如果程序中大量(10 個(gè)以上)使用重復(fù)觸發(fā)的定時(shí)器,或許值得考慮改用更高級(jí)的實(shí)現(xiàn)。我目前還沒(méi)有在一個(gè)程序里用過(guò)這么多定時(shí)器,暫時(shí)也不打算優(yōu)化 TimerQueue。

Boost.Asio Timer 示例

Boost.Asio 教程里以 Timer 和 Daytime 為例介紹 asio 的基本使用,daytime 已經(jīng)在前文“示例一”中介紹過(guò),這里著重談?wù)?Timer。Asio 有 5 個(gè) Timer 示例,muduo 把其中四個(gè)重新實(shí)現(xiàn)了一遍,并擴(kuò)充了第 5 個(gè)示例。

  1. 阻塞式的定時(shí),muduo 不支持這種用法,無(wú)代碼。
  2. 非阻塞定時(shí),見(jiàn) examples/asio/tutorial/timer2
  3. 在 TimerCallback 里傳遞參數(shù),見(jiàn) examples/asio/tutorial/timer3
  4. 以成員函數(shù)為 TimerCallback,見(jiàn) examples/asio/tutorial/timer4
  5. 在多線程中回調(diào),用 mutex 保護(hù)共享變量,見(jiàn) examples/asio/tutorial/timer5
  6. 在多線程中回調(diào),縮小臨界區(qū),把不需要互斥執(zhí)行的代碼移出來(lái),見(jiàn) examples/asio/tutorial/timer6

為節(jié)省篇幅,這里只列出 timer4:

   1: #include <muduo/net/EventLoop.h>
   2:  
   3: #include <iostream>
   4: #include <boost/bind.hpp>
   5: #include <boost/noncopyable.hpp>
   6:  
   7: class Printer : boost::noncopyable
   8: {
   9:  public:
  10:   Printer(muduo::net::EventLoop* loop)
  11:     : loop_(loop),
  12:       count_(0)
  13:   {
  14:     loop_->runAfter(1, boost::bind(&Printer::print, this));
  15:   }
  16:  
  17:   ~Printer()
  18:   {
  19:     std::cout << "Final count is " << count_ << "\n";
  20:   }
  21:  
  22:   void print()
  23:   {
  24:     if (count_ < 5)
  25:     {
  26:       std::cout << count_ << "\n";
  27:       ++count_;
  28:  
  29:       loop_->runAfter(1, boost::bind(&Printer::print, this));
  30:     }
  31:     else
  32:     {
  33:       loop_->quit();
  34:     }
  35:   }
  36:  
  37: private:
  38:   muduo::net::EventLoop* loop_;
  39:   int count_;
  40: };
  41:  
  42: int main()
  43: {
  44:   muduo::net::EventLoop loop;
  45:   Printer printer(&loop);
  46:   loop.loop();
  47: }

最后我再?gòu)?qiáng)調(diào)一遍,在非阻塞服務(wù)端編程中,絕對(duì)不能用  sleep 或類似的辦法來(lái)讓程序原地停留等待,這會(huì)讓程序失去響應(yīng),因?yàn)橹魇录h(huán)被掛起了,無(wú)法處理 IO 事件。這就像在 Windows 編程中絕對(duì)不能在消息循環(huán)里執(zhí)行耗時(shí)的代碼一樣,會(huì)讓程序界面失去響應(yīng)。Reactor 模式的網(wǎng)絡(luò)編程確實(shí)有些類似傳統(tǒng)的消息驅(qū)動(dòng)的 Windows 編程。對(duì)于“定時(shí)”任務(wù),就把它變成一個(gè)特定的消息,到時(shí)候觸發(fā)相應(yīng)的消息處理函數(shù)就行了。

Boost.Asio 的 timer 示例只用到了 EventLoop::runAfter,我再舉一個(gè) EventLoop::runEvery 的例子。

Java Netty 示例

Netty 是一個(gè)非常好的 Java NIO 網(wǎng)絡(luò)庫(kù),它附帶的示例程序echodiscard 兩個(gè)簡(jiǎn)單網(wǎng)絡(luò)協(xié)議,與前文不同,Netty 版的服務(wù)端有流量統(tǒng)計(jì)功能,這需要用到 EventLoop::runEvery。

這里列出 discard server 的代碼,其 client 的代碼類似前文的 chargen,為節(jié)省篇幅,請(qǐng)閱讀源碼 http://code.google.com/p/muduo/source/browse/trunk/examples/netty/

Discard server 注冊(cè)了一個(gè)間隔為 3 秒的定時(shí)器,調(diào)用 DiscardServer::printThroughput 打印出吞吐量。注意這段代碼用了整數(shù)的原子操作 AtomicInt64 來(lái)記錄收到的字節(jié)數(shù)和消息數(shù),乍看之下似乎沒(méi)有必要,其實(shí) DiscardServer 可以配置成多線程服務(wù)器,muduo TcpServer 有一個(gè)內(nèi)置的多線程模型,可以通過(guò) setThreadNum() 來(lái)開(kāi)啟。這個(gè)話題留到以后再細(xì)說(shuō)。

   1: #include <muduo/net/TcpServer.h>
   2:  
   3: #include <muduo/base/Atomic.h>
   4: #include <muduo/base/Logging.h>
   5: #include <muduo/base/Thread.h>
   6: #include <muduo/net/EventLoop.h>
   7: #include <muduo/net/InetAddress.h>
   8:  
   9: #include <boost/bind.hpp>
  10:  
  11: #include <utility>
  12:  
  13: #include <stdio.h>
  14: #include <unistd.h>
  15:  
  16: using namespace muduo;
  17: using namespace muduo::net;
  18:  
  19: int numThreads = 0;
  20:  
  21: class DiscardServer
  22: {
  23:  public:
  24:   DiscardServer(EventLoop* loop, const InetAddress& listenAddr)
  25:     : loop_(loop),
  26:       server_(loop, listenAddr, "DiscardServer"),
  27:       oldCounter_(0),
  28:       startTime_(Timestamp::now())
  29:   {
  30:     server_.setConnectionCallback(
  31:         boost::bind(&DiscardServer::onConnection, this, _1));
  32:     server_.setMessageCallback(
  33:         boost::bind(&DiscardServer::onMessage, this, _1, _2, _3));
  34:     server_.setThreadNum(numThreads);
  35:     loop->runEvery(3.0, boost::bind(&DiscardServer::printThroughput, this));
  36:   }
  37:  
  38:   void start()
  39:   {
  40:     LOG_INFO << "starting " << numThreads << " threads.";
  41:     server_.start();
  42:   }
  43:  
  44:  private:
  45:   void onConnection(const TcpConnectionPtr& conn)
  46:   {
  47:     LOG_TRACE << conn->peerAddress().toHostPort() << " -> "
  48:         << conn->localAddress().toHostPort() << " is "
  49:         << (conn->connected() ? "UP" : "DOWN");
  50:   }
  51:  
  52:   void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp)
  53:   {
  54:     size_t len = buf->readableBytes();
  55:     transferred_.add(len);
  56:     receivedMessages_.incrementAndGet();
  57:     buf->retrieveAll();
  58:   }
  59:  
  60:   void printThroughput()
  61:   {
  62:     Timestamp endTime = Timestamp::now();
  63:     int64_t newCounter = transferred_.get();
  64:     int64_t bytes = newCounter - oldCounter_;
  65:     int64_t msgs = receivedMessages_.getAndSet(0);
  66:     double time = timeDifference(endTime, startTime_);
  67:     printf("%4.3f MiB/s %4.3f Ki Msgs/s %6.2f bytes per msg\n",
  68:         static_cast<double>(bytes)/time/1024/1024,
  69:         static_cast<double>(msgs)/time/1024,
  70:         static_cast<double>(bytes)/static_cast<double>(msgs));
  71:  
  72:     oldCounter_ = newCounter;
  73:     startTime_ = endTime;
  74:   }
  75:  
  76:   EventLoop* loop_;
  77:   TcpServer server_;
  78:  
  79:   AtomicInt64 transferred_;
  80:   AtomicInt64 receivedMessages_;
  81:   int64_t oldCounter_;
  82:   Timestamp startTime_;
  83: };
  84:  
  85: int main(int argc, char* argv[])
  86: {
  87:   LOG_INFO << "pid = " << getpid() << ", tid = " << CurrentThread::tid();
  88:   if (argc > 1)
  89:   {
  90:     numThreads = atoi(argv[1]);
  91:   }
  92:   EventLoop loop;
  93:   InetAddress listenAddr(2009);
  94:   DiscardServer server(&loop, listenAddr);
  95:  
  96:   server.start();
  97:  
  98:   loop.loop();
  99: }

運(yùn)行方法,在同一臺(tái)機(jī)器的兩個(gè)命令行窗口分別運(yùn)行:

$ bin/netty_discard_server

$ bin/netty_discard_client 127.0.0.1 256

第一個(gè)窗口顯示吞吐量:

41.001 MiB/s 73.387 Ki Msgs/s 572.10 bytes per msg
72.441 MiB/s 129.593 Ki Msgs/s 572.40 bytes per msg
77.724 MiB/s 137.251 Ki Msgs/s 579.88 bytes per msg

改變第二個(gè)命令的最后一個(gè)參數(shù)(上面的 256),可以觀察不同的消息大小對(duì)吞吐量的影響。

練習(xí) 1:把二者的關(guān)系繪制成函數(shù)曲線,看看有什么規(guī)律,想想為什么。

練習(xí) 2:在局域網(wǎng)的兩臺(tái)機(jī)器上運(yùn)行客戶端和服務(wù)端,找出讓吞吐量達(dá)到最大的消息長(zhǎng)度。這個(gè)數(shù)字與練習(xí) 1 中的相比是大還是小?為什么?

有興趣的讀者可以對(duì)比一下 Netty 的吞吐量,muduo 應(yīng)該能輕松取勝。

discard client/server 測(cè)試的是單向吞吐量,echo client/server 測(cè)試的是雙向吞吐量。這兩個(gè)服務(wù)端都支持多個(gè)并發(fā)連接,兩個(gè)客戶端都是單連接的。本系列第 6 篇文章將會(huì)實(shí)現(xiàn)一個(gè) pingpong 協(xié)議,用來(lái)測(cè)試 muduo 在多線程大量連接情況下的表現(xiàn)。

(待續(xù))

posted on 2011-02-06 22:56 陳碩 閱讀(7653) 評(píng)論(3)  編輯 收藏 引用 所屬分類: muduo

評(píng)論

# re: Muduo 網(wǎng)絡(luò)編程示例之三:定時(shí)器 2014-08-21 14:49 ian

我的系統(tǒng)是CentOS 6.5;安裝了muduo-1.0.3。直接運(yùn)行../build/release/bin/asio_tutorial_timer2、netty_discard_server等關(guān)于定時(shí)器的程序會(huì)Illegal instruction(core dumped);而其他程序不行,請(qǐng)問(wèn)一般情況下是什么原因呢?  回復(fù)  更多評(píng)論   

# re: Muduo 網(wǎng)絡(luò)編程示例之三:定時(shí)器 2014-08-21 15:00 陳碩

@ian
把 CMakeLists.txt 中 -march=native 這句話去掉,重新編譯試試。  回復(fù)  更多評(píng)論   

# re: Muduo 網(wǎng)絡(luò)編程示例之三:定時(shí)器 2014-08-21 16:34 ian

@陳碩
謝謝陳老師這么快就回答了,去掉-march=native后重新編譯正常了。
  回復(fù)  更多評(píng)論   

<2014年8月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

導(dǎo)航

統(tǒng)計(jì)

常用鏈接

隨筆分類

隨筆檔案

相冊(cè)

搜索

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            一区二区三区自拍| 欧美一级播放| 亚洲欧美在线x视频| 亚洲精一区二区三区| 亚洲激情一区二区| 一级日韩一区在线观看| 亚洲女人av| 久久精品亚洲精品| 免费观看成人www动漫视频| 久久美女性网| 亚洲精品免费在线| 正在播放亚洲一区| 久久精品91| 欧美另类videos死尸| 国产精品天天看| 亚洲第一黄色网| 亚洲伊人观看| 农夫在线精品视频免费观看| 一本到高清视频免费精品| 欧美一二三区在线观看| 欧美国产一区二区| 国产日韩精品一区二区三区在线 | 亚洲激情另类| 亚洲一区二区三区中文字幕在线 | 国内精品视频在线观看| 亚洲黄色av| 性欧美video另类hd性玩具| 六月婷婷一区| 亚洲欧美日本另类| 欧美人牲a欧美精品| 狠狠色伊人亚洲综合成人| 亚洲宅男天堂在线观看无病毒| 久久久亚洲国产天美传媒修理工| 亚洲久久一区| 免费在线日韩av| 国产日韩av高清| 一区二区三区四区五区视频| 久久久最新网址| 亚洲午夜一区二区| 欧美日韩国产欧| 亚洲欧洲日产国产网站| 美女性感视频久久久| aa级大片欧美三级| 午夜综合激情| 亚洲视频一区二区免费在线观看| 久久精品国产99国产精品| 欧美日韩另类国产亚洲欧美一级| 激情欧美一区二区三区| 香蕉久久夜色精品| av成人动漫| 欧美日本不卡高清| 亚洲欧洲另类国产综合| 欧美超级免费视 在线| 久久精品国产69国产精品亚洲| 国产精品视频一| 欧美伊人久久大香线蕉综合69| 宅男精品视频| 国产精品国产精品国产专区不蜜| 99人久久精品视频最新地址| 亚洲成色精品| 欧美国产视频日韩| 一区二区福利| 亚洲一区二区免费视频| 国产精品大全| 欧美一区二区三区视频免费播放| 亚洲午夜免费福利视频| 国产精品视频1区| 久久激情综合网| 久久久国产精品一区| 在线视频国产日韩| 亚洲高清网站| 欧美日韩综合视频网址| 午夜精品福利电影| 欧美一区二区私人影院日本 | 欧美中文字幕视频在线观看| 亚洲欧美日韩中文在线制服| 亚洲每日更新| 国产精品日韩欧美一区| 久久免费国产| 欧美精品自拍| 欧美亚洲视频| 麻豆av一区二区三区久久| 日韩一区二区精品视频| 宅男噜噜噜66国产日韩在线观看| 国产精品免费观看视频| 久久影院午夜论| 欧美国产日本韩| 欧美在线播放| 欧美激情在线观看| 久久er精品视频| 欧美激情精品久久久久久黑人 | 亚洲欧美日韩在线不卡| 欧美一区二区视频网站| 亚洲精品久久久久久久久| 亚洲一区在线免费观看| 亚洲国产裸拍裸体视频在线观看乱了| 亚洲精品国精品久久99热一 | 欧美激情精品久久久久久蜜臀| 欧美激情精品久久久久久蜜臀| 亚洲一区二区在线看| 欧美资源在线| 亚洲欧美999| 欧美1区2区| 久久久久久一区二区| 欧美理论大片| 欧美~级网站不卡| 国产精品自拍一区| 亚洲精品日韩在线| 亚洲电影天堂av| 亚洲欧美日韩一区| 亚洲一区欧美激情| 欧美电影免费观看大全| 久久久成人精品| 国产精品视频一二三| 亚洲精品资源| 亚洲精品四区| 老牛嫩草一区二区三区日本| 久久黄金**| 国产精品一区二区久久国产| 日韩午夜精品视频| 日韩视频中文字幕| 久久综合久久综合九色| 久久久久久久久岛国免费| 国产精品亚洲一区| 亚洲影视综合| 午夜伦理片一区| 国产精品毛片大码女人| 亚洲视频在线播放| 羞羞漫画18久久大片| 国产精品一区一区| 亚洲男女自偷自拍| 久久国产主播| 国内精品久久久| 久久精品视频在线免费观看| 久久在线精品| 韩国v欧美v日本v亚洲v| 久久精品国产亚洲高清剧情介绍| 欧美中文字幕视频在线观看| 国产一区二区精品久久91| 欧美在线观看视频在线| 久久一区二区三区国产精品| 黄色一区二区三区四区| 久久深夜福利免费观看| 亚洲丰满少妇videoshd| 日韩视频在线观看| 欧美午夜不卡| 久久大综合网| 亚洲第一精品夜夜躁人人爽| 日韩亚洲欧美成人一区| 欧美性生交xxxxx久久久| 亚洲图片在区色| 久久久最新网址| 亚洲黄色大片| 国产精品毛片a∨一区二区三区|国| 亚洲欧美国产77777| 久久一区二区三区四区| 亚洲免费高清| 国产欧美精品在线播放| 久久伊人精品天天| 日韩小视频在线观看专区| 性欧美精品高清| 亚洲福利久久| 国产精品国产| 免费视频亚洲| 亚洲视频综合| 亚洲国产人成综合网站| 亚洲人体1000| 久久久久久久精| **欧美日韩vr在线| 欧美激情视频给我| 亚洲在线成人精品| 欧美大学生性色视频| 一区二区三区精品国产| 国产综合激情| 欧美性片在线观看| 久久最新视频| 亚洲欧美高清| 99国产精品久久久久久久成人热| 久久精品中文字幕一区| 亚洲一区二区三区四区五区黄| 在线成人亚洲| 国产九九精品视频| 欧美成人午夜影院| 欧美在线播放| 亚洲午夜国产一区99re久久| 欧美成人午夜影院| 久久精品国产一区二区三区免费看 | 欧美三级电影网| 老**午夜毛片一区二区三区| 亚洲一二三区在线观看| 亚洲国产精品久久久久婷婷884| 欧美在线电影| 亚洲深夜av| 亚洲精品一区二区三区四区高清| 国产色婷婷国产综合在线理论片a| 欧美精品国产精品日韩精品| 久久综合伊人77777蜜臀| 午夜精品在线| 亚洲综合成人婷婷小说| 亚洲精品国产精品乱码不99按摩 |