日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Libevent源码分析-----连接监听器evconnlistener

發布時間:2025/3/15 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Libevent源码分析-----连接监听器evconnlistener 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
出處:http://blog.csdn.net/luotuo44/article/details/38800363



使用evconnlistener:

? ? ? ? 基于event和event_base已經可以寫一個CS模型了。但是對于服務器端來說,仍然需要用戶自行調用socket、bind、listen、accept等步驟。這個過程有點繁瑣,為此在2.0.2-alpha版本的Libevent推出了一些對應的封裝函數。

? ? ? ??用戶只需初始化struct sockaddr_in結構體變量,然后把它作為參數傳給函數evconnlistener_new_bind即可。該函數會完成上面說到的那4個過程。下面的代碼是一個使用例子。

[cpp] view plaincopy print?
  • #include<netinet/in.h>??
  • #include<sys/socket.h>??
  • #include<unistd.h>??
  • ??
  • #include<stdio.h>??
  • #include<string.h>??
  • ??
  • #include<event.h>??
  • #include<listener.h>??
  • #include<bufferevent.h>??
  • #include<thread.h>??
  • ??
  • ??
  • void?listener_cb(evconnlistener?*listener,?evutil_socket_t?fd,??
  • ?????????????????struct?sockaddr?*sock,?int?socklen,?void?*arg);??
  • ??
  • void?socket_read_cb(bufferevent?*bev,?void?*arg);??
  • void?socket_error_cb(bufferevent?*bev,?short?events,?void?*arg);??
  • ??
  • int?main()??
  • {??
  • ????evthread_use_pthreads();//enable?threads??
  • ??
  • ????struct?sockaddr_in?sin;??
  • ????memset(&sin,?0,?sizeof(struct?sockaddr_in));??
  • ????sin.sin_family?=?AF_INET;??
  • ????sin.sin_port?=?htons(8989);??
  • ??
  • ????event_base?*base?=?event_base_new();??
  • ????evconnlistener?*listener??
  • ????????????=?evconnlistener_new_bind(base,?listener_cb,?base,??
  • ??????????????????????????????????????LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE?|?LEV_OPT_THREADSAFE,??
  • ??????????????????????????????????????10,?(struct?sockaddr*)&sin,??
  • ??????????????????????????????????????sizeof(struct?sockaddr_in));??
  • ??
  • ????event_base_dispatch(base);??
  • ??
  • ?????evconnlistener_free(listener);??
  • ????event_base_free(base);??
  • ??
  • ????return?0;??
  • }??
  • ??
  • ??
  • //有新的客戶端連接到服務器??
  • //當此函數被調用時,libevent已經幫我們accept了這個客戶端。該客戶端的??
  • //文件描述符為fd??
  • void?listener_cb(evconnlistener?*listener,?evutil_socket_t?fd,??
  • ?????????????????struct?sockaddr?*sock,?int?socklen,?void?*arg)??
  • {??
  • ????event_base?*base?=?(event_base*)arg;??
  • ??
  • ????//下面代碼是為這個fd創建一個bufferevent??
  • ????bufferevent?*bev?=??bufferevent_socket_new(base,?fd,??
  • ???????????????????????????????????????????????BEV_OPT_CLOSE_ON_FREE);??
  • ??
  • ????bufferevent_setcb(bev,?socket_read_cb,?NULL,?socket_error_cb,?NULL);??
  • ????bufferevent_enable(bev,?EV_READ?|?EV_PERSIST);??
  • }??
  • ??
  • ??
  • void?socket_read_cb(bufferevent?*bev,?void?*arg)??
  • {??
  • ????char?msg[4096];??
  • ??
  • ????size_t?len?=?bufferevent_read(bev,?msg,?sizeof(msg)-1?);??
  • ??
  • ????msg[len]?=?'\0';??
  • ????printf("server?read?the?data?%s\n",?msg);??
  • ??
  • ????char?reply[]?=?"I?has?read?your?data";??
  • ????bufferevent_write(bev,?reply,?strlen(reply)?);??
  • }??
  • ??
  • ??
  • void?socket_error_cb(bufferevent?*bev,?short?events,?void?*arg)??
  • {??
  • ????if?(events?&?BEV_EVENT_EOF)??
  • ????????printf("connection?closed\n");??
  • ????else?if?(events?&?BEV_EVENT_ERROR)??
  • ????????printf("some?other?error\n");??
  • ??
  • ????//這將自動close套接字和free讀寫緩沖區??
  • ????bufferevent_free(bev);??
  • }??
  • #include<netinet/in.h> #include<sys/socket.h> #include<unistd.h>#include<stdio.h> #include<string.h>#include<event.h> #include<listener.h> #include<bufferevent.h> #include<thread.h>void listener_cb(evconnlistener *listener, evutil_socket_t fd,struct sockaddr *sock, int socklen, void *arg);void socket_read_cb(bufferevent *bev, void *arg); void socket_error_cb(bufferevent *bev, short events, void *arg);int main() {evthread_use_pthreads();//enable threadsstruct sockaddr_in sin;memset(&sin, 0, sizeof(struct sockaddr_in));sin.sin_family = AF_INET;sin.sin_port = htons(8989);event_base *base = event_base_new();evconnlistener *listener= evconnlistener_new_bind(base, listener_cb, base,LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE | LEV_OPT_THREADSAFE,10, (struct sockaddr*)&sin,sizeof(struct sockaddr_in));event_base_dispatch(base);evconnlistener_free(listener);event_base_free(base);return 0; }//有新的客戶端連接到服務器 //當此函數被調用時,libevent已經幫我們accept了這個客戶端。該客戶端的 //文件描述符為fd void listener_cb(evconnlistener *listener, evutil_socket_t fd,struct sockaddr *sock, int socklen, void *arg) {event_base *base = (event_base*)arg;//下面代碼是為這個fd創建一個buffereventbufferevent *bev = bufferevent_socket_new(base, fd,BEV_OPT_CLOSE_ON_FREE);bufferevent_setcb(bev, socket_read_cb, NULL, socket_error_cb, NULL);bufferevent_enable(bev, EV_READ | EV_PERSIST); }void socket_read_cb(bufferevent *bev, void *arg) {char msg[4096];size_t len = bufferevent_read(bev, msg, sizeof(msg)-1 );msg[len] = '\0';printf("server read the data %s\n", msg);char reply[] = "I has read your data";bufferevent_write(bev, reply, strlen(reply) ); }void socket_error_cb(bufferevent *bev, short events, void *arg) {if (events & BEV_EVENT_EOF)printf("connection closed\n");else if (events & BEV_EVENT_ERROR)printf("some other error\n");//這將自動close套接字和free讀寫緩沖區bufferevent_free(bev); }

    ? ? ? ??上面的代碼是一個服務器端的例子,客戶端代碼可以使用《Libevent使用例子,從簡單到復雜》博文中的客戶端。這里就不貼客戶端代碼了。

    ?

    ? ? ? ??從上面代碼可以看到,當服務器端監聽到一個客戶端的連接請求后,就會調用listener_cb這個回調函數。這個回調函數是在evconnlistener_new_bind函數中設置的?,F在來看一下這個函數的參數有哪些,下面是其函數原型。

    [cpp] view plaincopy print?
  • //listener.h文件??
  • typedef?void?(*evconnlistener_cb)(struct?evconnlistener?*,?evutil_socket_t,?struct?sockaddr?*,?int?socklen,?void?*);??
  • ??
  • struct?evconnlistener?*evconnlistener_new_bind(struct?event_base?*base,??
  • ????evconnlistener_cb?cb,?void?*ptr,?unsigned?flags,?int?backlog,??
  • ????const?struct?sockaddr?*sa,?int?socklen);??
  • //listener.h文件 typedef void (*evconnlistener_cb)(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *);struct evconnlistener *evconnlistener_new_bind(struct event_base *base,evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,const struct sockaddr *sa, int socklen);

    ? ? ? ??第一個參數是很熟悉的event_base,無論怎么樣都是離不開event_base這個發動機的。

    ? ? ? ??第二個參數是一個函數指針,該函數指針的格式如代碼所示。當有新的客戶端請求連接時,該函數就會調用。要注意的是:當這個回調函數被調用時,Libevent已經幫我們accept了這個客戶端。所以,該回調函數有一個參數是文件描述符fd。我們直接使用這個fd即可。真是方便。這個參數是可以為NULL的,此時用戶并不能接收到客戶端。當用戶調用evconnlistener_set_cb函數設置回調函數后,就可以了。

    ? ? ? ??第三個參數是傳給回調函數的用戶參數,作用就像event_new函數的最后一個參數。

    ? ? ? ??參數flags是一些標志值,有下面這些:

    • LEV_OPT_LEAVE_SOCKETS_BLOCKING:默認情況下,當連接監聽器接收到新的客戶端socket連接后,會把該socket設置為非阻塞的。如果設置該選項,那么就把之客戶端socket保留為阻塞的
    • LEV_OPT_CLOSE_ON_FREE:當連接監聽器釋放時,會自動關閉底層的socket
    • LEV_OPT_CLOSE_ON_EXEC:為底層的socket設置close-on-exec標志
    • LEV_OPT_REUSEABLE:?在某些平臺,默認情況下當一個監聽socket被關閉時,其他socket不能馬上綁定到同一個端口,要等一會兒才行。設置該標志后,Libevent會把該socket設置成reuseable。這樣,關閉該socket后,其他socket就能馬上使用同一個端口
    • LEV_OPT_THREADSAFE:為連接監聽器分配鎖。這樣可以確保線程安全

    ? ? ? ??參數backlog是系統調用listen的第二個參數。最后兩個參數就不多說了。



    evconnlistener的封裝:

    ? ? ? ??接下來看一下Libevent是怎么封裝evconnlistener的。


    用到的結構體:

    [cpp] view plaincopy print?
  • //listener.c文件??
  • struct?evconnlistener_ops?{//一系列的工作函數??
  • ????int?(*enable)(struct?evconnlistener?*);??
  • ????int?(*disable)(struct?evconnlistener?*);??
  • ????void?(*destroy)(struct?evconnlistener?*);??
  • ????void?(*shutdown)(struct?evconnlistener?*);??
  • ????evutil_socket_t?(*getfd)(struct?evconnlistener?*);??
  • ????struct?event_base?*(*getbase)(struct?evconnlistener?*);??
  • };??
  • ??
  • struct?evconnlistener?{??
  • ????const?struct?evconnlistener_ops?*ops;//操作函數??
  • ????void?*lock;?//鎖變量,用于線程安全??
  • ????evconnlistener_cb?cb;//用戶的回調函數??
  • ????evconnlistener_errorcb?errorcb;//發生錯誤時的回調函數??
  • ????void?*user_data;//回調函數的參數??
  • ????unsigned?flags;//屬性標志??
  • ????short?refcnt;//引用計數??
  • ????unsigned?enabled?:?1;//位域為1.即只需一個比特位來存儲這個成員??
  • };??
  • ??
  • struct?evconnlistener_event?{??
  • ????struct?evconnlistener?base;??
  • ????struct?event?listener;?//內部event,插入到event_base??
  • };??
  • //listener.c文件 struct evconnlistener_ops {//一系列的工作函數int (*enable)(struct evconnlistener *);int (*disable)(struct evconnlistener *);void (*destroy)(struct evconnlistener *);void (*shutdown)(struct evconnlistener *);evutil_socket_t (*getfd)(struct evconnlistener *);struct event_base *(*getbase)(struct evconnlistener *); };struct evconnlistener {const struct evconnlistener_ops *ops;//操作函數void *lock; //鎖變量,用于線程安全evconnlistener_cb cb;//用戶的回調函數evconnlistener_errorcb errorcb;//發生錯誤時的回調函數void *user_data;//回調函數的參數unsigned flags;//屬性標志short refcnt;//引用計數unsigned enabled : 1;//位域為1.即只需一個比特位來存儲這個成員 };struct evconnlistener_event {struct evconnlistener base;struct event listener; //內部event,插入到event_base };

    ? ? ? ??在evconnlistener_event結構體有一個event結構體。可以想象,在實現時必然是將服務器端的socket fd賦值給struct event 類型變量listener的fd成員。然后將listener加入到event_base,這樣就完成了自動監聽工作。這也回歸到之前學過的內容。


    ? ? ? ??下面看一下具體是怎么實現的。

    初始化服務器socket:

    [cpp] view plaincopy print?
  • //listener.c文件??
  • struct?evconnlistener?*??
  • evconnlistener_new_bind(struct?event_base?*base,?evconnlistener_cb?cb,??
  • ????void?*ptr,?unsigned?flags,?int?backlog,?const?struct?sockaddr?*sa,??
  • ????int?socklen)??
  • {??
  • ????struct?evconnlistener?*listener;??
  • ????evutil_socket_t?fd;??
  • ????int?on?=?1;??
  • ????int?family?=?sa???sa->sa_family?:?AF_UNSPEC;??
  • ??
  • ????//監聽個數不能為0??
  • ????if?(backlog?==?0)??
  • ????????return?NULL;??
  • ??
  • ????fd?=?socket(family,?SOCK_STREAM,?0);??
  • ????if?(fd?==?-1)??
  • ????????return?NULL;??
  • ??
  • ????//LEV_OPT_LEAVE_SOCKETS_BLOCKING選項是應用于accept到的客戶端socket??
  • ????//所以對于服務器端的socket,直接將之設置為非阻塞的??
  • ????if?(evutil_make_socket_nonblocking(fd)?<?0)?{??
  • ????????evutil_closesocket(fd);??
  • ????????return?NULL;??
  • ????}??
  • ??
  • ????if?(flags?&?LEV_OPT_CLOSE_ON_EXEC)?{??
  • ????????if?(evutil_make_socket_closeonexec(fd)?<?0)?{??
  • ????????????evutil_closesocket(fd);??
  • ????????????return?NULL;??
  • ????????}??
  • ????}??
  • ??
  • ????if?(setsockopt(fd,?SOL_SOCKET,?SO_KEEPALIVE,?(void*)&on,?sizeof(on))<0)?{??
  • ????????evutil_closesocket(fd);??
  • ????????return?NULL;??
  • ????}??
  • ????if?(flags?&?LEV_OPT_REUSEABLE)?{??
  • ????????if?(evutil_make_listen_socket_reuseable(fd)?<?0)?{??
  • ????????????evutil_closesocket(fd);??
  • ????????????return?NULL;??
  • ????????}??
  • ????}??
  • ??
  • ????if?(sa)?{??
  • ????????if?(bind(fd,?sa,?socklen)<0)?{//綁定??
  • ????????????evutil_closesocket(fd);??
  • ????????????return?NULL;??
  • ????????}??
  • ????}??
  • ??
  • ????listener?=?evconnlistener_new(base,?cb,?ptr,?flags,?backlog,?fd);??
  • ????if?(!listener)?{??
  • ????????evutil_closesocket(fd);??
  • ????????return?NULL;??
  • ????}??
  • ??
  • ????return?listener;??
  • }??
  • //listener.c文件 struct evconnlistener * evconnlistener_new_bind(struct event_base *base, evconnlistener_cb cb,void *ptr, unsigned flags, int backlog, const struct sockaddr *sa,int socklen) {struct evconnlistener *listener;evutil_socket_t fd;int on = 1;int family = sa ? sa->sa_family : AF_UNSPEC;//監聽個數不能為0if (backlog == 0)return NULL;fd = socket(family, SOCK_STREAM, 0);if (fd == -1)return NULL;//LEV_OPT_LEAVE_SOCKETS_BLOCKING選項是應用于accept到的客戶端socket//所以對于服務器端的socket,直接將之設置為非阻塞的if (evutil_make_socket_nonblocking(fd) < 0) {evutil_closesocket(fd);return NULL;}if (flags & LEV_OPT_CLOSE_ON_EXEC) {if (evutil_make_socket_closeonexec(fd) < 0) {evutil_closesocket(fd);return NULL;}}if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))<0) {evutil_closesocket(fd);return NULL;}if (flags & LEV_OPT_REUSEABLE) {if (evutil_make_listen_socket_reuseable(fd) < 0) {evutil_closesocket(fd);return NULL;}}if (sa) {if (bind(fd, sa, socklen)<0) {//綁定evutil_closesocket(fd);return NULL;}}listener = evconnlistener_new(base, cb, ptr, flags, backlog, fd);if (!listener) {evutil_closesocket(fd);return NULL;}return listener; }

    ? ? ? ??evconnlistener_new_bind函數申請一個socket,然后對之進行一些有關非阻塞、重用、保持連接的處理、綁定到特定的IP和端口。最后把業務邏輯交給evconnlistener_new處理。


    [cpp] view plaincopy print?
  • //listener.c文件??
  • static?const?struct?evconnlistener_ops?evconnlistener_event_ops?=?{??
  • ????event_listener_enable,??
  • ????event_listener_disable,??
  • ????event_listener_destroy,??
  • ????NULL,?/*?shutdown?*/??
  • ????event_listener_getfd,??
  • ????event_listener_getbase??
  • };??
  • ??
  • ??
  • struct?evconnlistener?*??
  • evconnlistener_new(struct?event_base?*base,??
  • ????evconnlistener_cb?cb,?void?*ptr,?unsigned?flags,?int?backlog,??
  • ????evutil_socket_t?fd)??
  • {??
  • ????struct?evconnlistener_event?*lev;??
  • ??
  • ????if?(backlog?>?0)?{??
  • ????????if?(listen(fd,?backlog)?<?0)??
  • ????????????return?NULL;??
  • ????}?else?if?(backlog?<?0)?{??
  • ????????if?(listen(fd,?128)?<?0)??
  • ????????????return?NULL;??
  • ????}??
  • ??
  • ????lev?=?mm_calloc(1,?sizeof(struct?evconnlistener_event));??
  • ????if?(!lev)??
  • ????????return?NULL;??
  • ??
  • ????//賦值??
  • ????lev->base.ops?=?&evconnlistener_event_ops;??
  • ????lev->base.cb?=?cb;??
  • ????lev->base.user_data?=?ptr;??
  • ????lev->base.flags?=?flags;??
  • ????lev->base.refcnt?=?1;??
  • ??
  • ????if?(flags?&?LEV_OPT_THREADSAFE)?{//線程安全就需要分配鎖??
  • ????????EVTHREAD_ALLOC_LOCK(lev->base.lock,?EVTHREAD_LOCKTYPE_RECURSIVE);??
  • ????}??
  • ??
  • ????//在多路IO復用函數中,新客戶端的連接請求也被當作讀事件??
  • ????event_assign(&lev->listener,?base,?fd,?EV_READ|EV_PERSIST,??
  • ????????listener_read_cb,?lev);??
  • ??
  • ????//會調用event_add,把event加入到event_base中??
  • ????evconnlistener_enable(&lev->base);??
  • ??
  • ????return?&lev->base;??
  • }??
  • ??
  • int??
  • evconnlistener_enable(struct?evconnlistener?*lev)??
  • {??
  • ????int?r;??
  • ????LOCK(lev);??
  • ????lev->enabled?=?1;??
  • ????if?(lev->cb)??
  • ????????r?=?lev->ops->enable(lev);//實際上是調用下面的event_listener_enable函數??
  • ????else??
  • ????????r?=?0;??
  • ????UNLOCK(lev);??
  • ????return?r;??
  • }??
  • ??
  • static?int??
  • event_listener_enable(struct?evconnlistener?*lev)??
  • {??
  • ????struct?evconnlistener_event?*lev_e?=??
  • ????????EVUTIL_UPCAST(lev,?struct?evconnlistener_event,?base);??
  • ??
  • ????//加入到event_base,完成監聽工作。??
  • ????return?event_add(&lev_e->listener,?NULL);??
  • }??
  • //listener.c文件 static const struct evconnlistener_ops evconnlistener_event_ops = {event_listener_enable,event_listener_disable,event_listener_destroy,NULL, /* shutdown */event_listener_getfd,event_listener_getbase };struct evconnlistener * evconnlistener_new(struct event_base *base,evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,evutil_socket_t fd) {struct evconnlistener_event *lev;if (backlog > 0) {if (listen(fd, backlog) < 0)return NULL;} else if (backlog < 0) {if (listen(fd, 128) < 0)return NULL;}lev = mm_calloc(1, sizeof(struct evconnlistener_event));if (!lev)return NULL;//賦值lev->base.ops = &evconnlistener_event_ops;lev->base.cb = cb;lev->base.user_data = ptr;lev->base.flags = flags;lev->base.refcnt = 1;if (flags & LEV_OPT_THREADSAFE) {//線程安全就需要分配鎖EVTHREAD_ALLOC_LOCK(lev->base.lock, EVTHREAD_LOCKTYPE_RECURSIVE);}//在多路IO復用函數中,新客戶端的連接請求也被當作讀事件event_assign(&lev->listener, base, fd, EV_READ|EV_PERSIST,listener_read_cb, lev);//會調用event_add,把event加入到event_base中evconnlistener_enable(&lev->base);return &lev->base; }int evconnlistener_enable(struct evconnlistener *lev) {int r;LOCK(lev);lev->enabled = 1;if (lev->cb)r = lev->ops->enable(lev);//實際上是調用下面的event_listener_enable函數elser = 0;UNLOCK(lev);return r; }static int event_listener_enable(struct evconnlistener *lev) {struct evconnlistener_event *lev_e =EVUTIL_UPCAST(lev, struct evconnlistener_event, base);//加入到event_base,完成監聽工作。return event_add(&lev_e->listener, NULL); }

    ? ? ? ??幾個函數的一路調用,思路還是挺清晰的。就是申請一個socket,進行一些處理,然后用之賦值給event。最后把之add到event_base中。event_base會對新客戶端的請求連接進行監聽。


    ? ? ? ??在evconnlistener_enable函數里面,如果用戶沒有設置回調函數,那么就不會調用event_listener_enable。也就是說并不會add到event_base中。

    ? ? ? ??event_listener_enable函數里面的宏EVUTIL_UPCAST可以根據結構體成員變量的地址推算出結構體的起始地址。有關這個宏,可以查看”結構體偏移量”。


    處理客戶端的連接請求:

    ? ? ? ??現在來看一下event的回調函數listener_read_cb。

    [cpp] view plaincopy print?
  • //listener.c文件??
  • static?void??
  • listener_read_cb(evutil_socket_t?fd,?short?what,?void?*p)??
  • {??
  • ????struct?evconnlistener?*lev?=?p;??
  • ????int?err;??
  • ????evconnlistener_cb?cb;??
  • ????evconnlistener_errorcb?errorcb;??
  • ????void?*user_data;??
  • ????LOCK(lev);??
  • ????while?(1)?{?//可能有多個客戶端同時請求連接??
  • ????????struct?sockaddr_storage?ss;??
  • #ifdef?WIN32??
  • ????????int?socklen?=?sizeof(ss);??
  • #else??
  • ????????socklen_t?socklen?=?sizeof(ss);??
  • #endif??
  • ????????evutil_socket_t?new_fd?=?accept(fd,?(struct?sockaddr*)&ss,?&socklen);??
  • ????????if?(new_fd?<?0)??
  • ????????????break;??
  • ????????if?(socklen?==?0)?{??
  • ????????????/*?This?can?happen?with?some?older?linux?kernels?in?
  • ?????????????*?response?to?nmap.?*/??
  • ????????????evutil_closesocket(new_fd);??
  • ????????????continue;??
  • ????????}??
  • ??
  • ????????if?(!(lev->flags?&?LEV_OPT_LEAVE_SOCKETS_BLOCKING))??
  • ????????????evutil_make_socket_nonblocking(new_fd);??
  • ??
  • ????????//用戶還沒設置連接監聽器的回調函數??
  • ????????if?(lev->cb?==?NULL)?{??
  • ????????????UNLOCK(lev);??
  • ????????????return;??
  • ????????}??
  • ??
  • ????????//由于refcnt被初始化為1.這里有++了,所以一般情況下并不會進入下面的??
  • ????????//if判斷里面。但如果程在下面UNLOCK之后,第二個線調用evconnlistener_free??
  • ????????//釋放這個evconnlistener時,就有可能使得refcnt為1了。即進入那個判斷體里??
  • ????????//執行listener_decref_and_unlock。在下面會討論這個問題。??
  • ????????++lev->refcnt;??
  • ????????cb?=?lev->cb;??
  • ????????user_data?=?lev->user_data;??
  • ????????UNLOCK(lev);??
  • ????????cb(lev,?new_fd,?(struct?sockaddr*)&ss,?(int)socklen,??
  • ????????????user_data);//調用用戶設置的回調函數,讓用戶處理這個fd??
  • ????????LOCK(lev);??
  • ????????if?(lev->refcnt?==?1)?{??
  • ????????????int?freed?=?listener_decref_and_unlock(lev);??
  • ????????????EVUTIL_ASSERT(freed);??
  • ????????????return;??
  • ????????}??
  • ????????--lev->refcnt;??
  • ????}??
  • ??????
  • ????err?=?evutil_socket_geterror(fd);??
  • ????if?(EVUTIL_ERR_ACCEPT_RETRIABLE(err))?{//還可以accept??
  • ????????UNLOCK(lev);??
  • ????????return;??
  • ????}??
  • ??
  • ????//當有錯誤發生時才會運行到這里??
  • ????if?(lev->errorcb?!=?NULL)?{??
  • ????????++lev->refcnt;??
  • ????????errorcb?=?lev->errorcb;??
  • ????????user_data?=?lev->user_data;??
  • ????????UNLOCK(lev);??
  • ????????errorcb(lev,?user_data);//調用用戶設置的錯誤回調函數??
  • ????????LOCK(lev);??
  • ????????listener_decref_and_unlock(lev);??
  • ????}??
  • }??
  • //listener.c文件 static void listener_read_cb(evutil_socket_t fd, short what, void *p) {struct evconnlistener *lev = p;int err;evconnlistener_cb cb;evconnlistener_errorcb errorcb;void *user_data;LOCK(lev);while (1) { //可能有多個客戶端同時請求連接struct sockaddr_storage ss; #ifdef WIN32int socklen = sizeof(ss); #elsesocklen_t socklen = sizeof(ss); #endifevutil_socket_t new_fd = accept(fd, (struct sockaddr*)&ss, &socklen);if (new_fd < 0)break;if (socklen == 0) {/* This can happen with some older linux kernels in* response to nmap. */evutil_closesocket(new_fd);continue;}if (!(lev->flags & LEV_OPT_LEAVE_SOCKETS_BLOCKING))evutil_make_socket_nonblocking(new_fd);//用戶還沒設置連接監聽器的回調函數if (lev->cb == NULL) {UNLOCK(lev);return;}//由于refcnt被初始化為1.這里有++了,所以一般情況下并不會進入下面的//if判斷里面。但如果程在下面UNLOCK之后,第二個線調用evconnlistener_free//釋放這個evconnlistener時,就有可能使得refcnt為1了。即進入那個判斷體里//執行listener_decref_and_unlock。在下面會討論這個問題。++lev->refcnt;cb = lev->cb;user_data = lev->user_data;UNLOCK(lev);cb(lev, new_fd, (struct sockaddr*)&ss, (int)socklen,user_data);//調用用戶設置的回調函數,讓用戶處理這個fdLOCK(lev);if (lev->refcnt == 1) {int freed = listener_decref_and_unlock(lev);EVUTIL_ASSERT(freed);return;}--lev->refcnt;}err = evutil_socket_geterror(fd);if (EVUTIL_ERR_ACCEPT_RETRIABLE(err)) {//還可以acceptUNLOCK(lev);return;}//當有錯誤發生時才會運行到這里if (lev->errorcb != NULL) {++lev->refcnt;errorcb = lev->errorcb;user_data = lev->user_data;UNLOCK(lev);errorcb(lev, user_data);//調用用戶設置的錯誤回調函數LOCK(lev);listener_decref_and_unlock(lev);} }

    ? ? ? ??這個函數所做的工作也比較簡單,就是accept客戶端,然后調用用戶設置的回調函數。所以,用戶回調函數的參數fd是一個已經連接好了的socket。


    ? ? ? ??上面函數說到了錯誤回調函數,可以通過下面的函數設置連接監聽器的錯誤監聽函數。

    [cpp] view plaincopy print?
  • //listener.h文件??
  • typedef?void?(*evconnlistener_errorcb)(struct?evconnlistener?*,?void?*);??
  • ??
  • //listener.c文件??
  • void??
  • evconnlistener_set_error_cb(struct?evconnlistener?*lev,??
  • ????evconnlistener_errorcb?errorcb)??
  • {??
  • ????LOCK(lev);??
  • ????lev->errorcb?=?errorcb;??
  • ????UNLOCK(lev);??
  • }??
  • //listener.h文件 typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *);//listener.c文件 void evconnlistener_set_error_cb(struct evconnlistener *lev,evconnlistener_errorcb errorcb) {LOCK(lev);lev->errorcb = errorcb;UNLOCK(lev); }


    釋放evconnlistener:

    ? ? ? ??調用evconnlistener_free可以釋放一個evconnlistener。由于evconnlistener擁有一些系統資源,在釋放evconnlistener_free的時候會釋放這些系統資源。

    [cpp] view plaincopy print?
  • //listener.c文件??
  • void??
  • evconnlistener_free(struct?evconnlistener?*lev)??
  • {??
  • ????LOCK(lev);??
  • ????lev->cb?=?NULL;??
  • ????lev->errorcb?=?NULL;??
  • ????if?(lev->ops->shutdown)//這里的shutdown為NULL??
  • ????????lev->ops->shutdown(lev);??
  • ??
  • ????//引用次數減一,并解鎖??
  • ????listener_decref_and_unlock(lev);??
  • }??
  • ??
  • static?int??
  • listener_decref_and_unlock(struct?evconnlistener?*listener)??
  • {??
  • ????int?refcnt?=?--listener->refcnt;??
  • ????if?(refcnt?==?0)?{??
  • ????????//實際調用event_listener_destroy??
  • ????????listener->ops->destroy(listener);??
  • ????????UNLOCK(listener);??
  • ????????//釋放鎖??
  • ????????EVTHREAD_FREE_LOCK(listener->lock,?EVTHREAD_LOCKTYPE_RECURSIVE);??
  • ????????mm_free(listener);??
  • ????????return?1;??
  • ????}?else?{??
  • ????????UNLOCK(listener);??
  • ????????return?0;??
  • ????}??
  • }??
  • ??
  • static?void??
  • event_listener_destroy(struct?evconnlistener?*lev)??
  • {??
  • ????struct?evconnlistener_event?*lev_e?=??
  • ????????EVUTIL_UPCAST(lev,?struct?evconnlistener_event,?base);??
  • ??
  • ????//把event從event_base中刪除??
  • ????event_del(&lev_e->listener);??
  • ????if?(lev->flags?&?LEV_OPT_CLOSE_ON_FREE)//如果用戶設置了這個選項,那么要關閉socket??
  • ????????evutil_closesocket(event_get_fd(&lev_e->listener));??
  • }??
  • //listener.c文件 void evconnlistener_free(struct evconnlistener *lev) {LOCK(lev);lev->cb = NULL;lev->errorcb = NULL;if (lev->ops->shutdown)//這里的shutdown為NULLlev->ops->shutdown(lev);//引用次數減一,并解鎖listener_decref_and_unlock(lev); }static int listener_decref_and_unlock(struct evconnlistener *listener) {int refcnt = --listener->refcnt;if (refcnt == 0) {//實際調用event_listener_destroylistener->ops->destroy(listener);UNLOCK(listener);//釋放鎖EVTHREAD_FREE_LOCK(listener->lock, EVTHREAD_LOCKTYPE_RECURSIVE);mm_free(listener);return 1;} else {UNLOCK(listener);return 0;} }static void event_listener_destroy(struct evconnlistener *lev) {struct evconnlistener_event *lev_e =EVUTIL_UPCAST(lev, struct evconnlistener_event, base);//把event從event_base中刪除event_del(&lev_e->listener);if (lev->flags & LEV_OPT_CLOSE_ON_FREE)//如果用戶設置了這個選項,那么要關閉socketevutil_closesocket(event_get_fd(&lev_e->listener)); }


    ? ? ? ??要注意一點,LEV_OPT_CLOSE_ON_FREE選項關閉的是服務器端的監聽socket,而非那些連接客戶端的socket。



    ? ? ? ??現在來說一下那個listener_decref_and_unlock。前面注釋說到,在函數listener_read_cb中,一般情況下是不會調用listener_decref_and_unlock,但在多線程的時候可能會調用。這種特殊情況是:當主線程accept到一個新客戶端時,會解鎖,并調用用戶設置的回調函數。此時,引用計數等于2。就在這個時候,第二個線程執行evconnlistener_free函數。該函數會執行listener_decref_and_unlock。明顯主線程還在用這個evconnlistener,肯定不能刪除。此時引用計數也等于2也不會刪除。但用戶已經調用了evconnlistener_free。Libevent必須要響應。當第二個線程執行完后,主線程搶到CPU,此時引用計數就變成1了,也就進入到if判斷里面了。在判斷體里面執行函數listener_decref_and_unlock,并且完成刪除工作。

    ?

    ? ? ? ??總得來說,Libevent封裝的這個evconnlistener和一系列操作函數,還是比較簡單的。思路也比較清晰。

    總結

    以上是生活随笔為你收集整理的Libevent源码分析-----连接监听器evconnlistener的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    婷婷久久精品 | 国产精品久久久久久久久大全 | 亚洲精品综合在线观看 | 国产亚洲精品日韩在线tv黄 | 日韩欧美在线高清 | 久久 亚洲视频 | 日韩69av | 久久久久观看 | 在线观看v片 | 97在线公开视频 | 97视频网址| 亚洲国产片色 | 日韩欧美在线观看 | 91精品国产入口 | 久热精品国产 | 免费看三级 | 在线观看av麻豆 | 最近中文字幕高清字幕免费mv | 中文字幕在线影院 | 91麻豆福利 | 麻豆传媒视频在线免费观看 | 午夜三级毛片 | 韩国av一区二区三区在线观看 | 日日夜夜免费精品视频 | 国产又粗又硬又长又爽的视频 | 中文字幕亚洲五码 | 国产精品欧美久久久久无广告 | 麻豆va一区二区三区久久浪 | 中文国产字幕在线观看 | 激情偷乱人伦小说视频在线观看 | 国产婷婷色 | av激情五月 | 国产乱码精品一区二区蜜臀 | 91精品婷婷国产综合久久蝌蚪 | 最近中文字幕在线播放 | av免费电影在线 | av中文电影 | 色噜噜在线观看 | 天天操偷偷干 | 99热官网 | 国产精品私人影院 | 免费看黄色大全 | 成年人在线播放视频 | 久久久高清 | 在线看一级片 | 精品麻豆| 91tv国产成人福利 | 久久久国产精品成人免费 | 天天天射| 丁香六月在线观看 | 五月激情站 | 久久试看| 中文字幕在线看片 | 久久国产精品久久国产精品 | 美女在线黄 | 69国产精品成人在线播放 | 亚洲涩涩一区 | 免费成人在线视频网站 | 最新国产精品拍自在线播放 | 亚洲国产成人精品在线 | 最近中文字幕高清字幕免费mv | 91在线小视频 | 人人舔人人射 | 免费高清在线观看成人 | 在线观看亚洲精品 | 三级av小说| 亚洲国产免费看 | 日本精品久久久久 | 天天操网| 日韩在线视频在线观看 | 黄网站色 | 国产手机视频在线播放 | 欧美视频网址 | 五月天网站在线 | 色婷婷亚洲婷婷 | 亚洲精品美女久久 | 五月激情综合婷婷 | 日韩欧美视频在线免费观看 | 九九爱免费视频 | 偷拍精偷拍精品欧洲亚洲网站 | 久久久99久久 | 亚洲综合在线五月天 | 欧美激情精品久久 | 国产96av | 亚洲精品久久在线 | 五月天激情婷婷 | 中文字幕在线播放日韩 | a视频在线观看 | 亚洲三级av | 国产精品一区在线 | 色网站在线 | 91av在线免费视频 | 在线播放视频一区 | 日韩 精品 一区 国产 麻豆 | 精品视频区 | 成人va在线观看 | 久久免费久久 | 日韩精品中文字幕在线观看 | 亚洲午夜久久久久久久久 | 99精品久久久久 | 最近中文字幕免费 | 日韩精品专区在线影院重磅 | 韩国精品福利一区二区三区 | 国产精品久久久久久久久久久久午 | 69国产精品成人在线播放 | 91九色丨porny丨丰满6 | 日韩狠狠操 | 精品久久久久久亚洲综合网站 | 国产一二区精品 | 久色小说| 午夜精品福利一区二区三区蜜桃 | 国产精品毛片完整版 | 国产精品国产毛片 | 亚洲区另类春色综合小说 | 色九色 | 国产亚洲激情视频在线 | av资源在线看 | 97视频免费在线观看 | www蜜桃视频 | 丁香六月在线观看 | 久久国产精品久久久久 | 色网站免费在线看 | 日韩欧美视频免费在线观看 | 韩国av在线播放 | 久久久久99精品国产片 | 精品久久久久久国产偷窥 | 超碰国产在线播放 | 中文在线a在线 | 亚洲在线视频网站 | 美女视频a美女大全免费下载蜜臀 | 国产99久久 | 久精品视频免费观看2 | 亚洲精品视频网址 | 国产在线精品国自产拍影院 | 96精品视频 | 91高清免费在线观看 | 五月婷婷播播 | 精品国产网址 | 激情久久综合网 | 深夜免费福利 | 成人亚洲综合 | 天天综合色天天综合 | 国产日韩欧美在线看 | 免费毛片一区二区三区久久久 | 99久久精品免费看国产一区二区三区 | 日韩视频一区二区 | 国产精品乱码久久久久 | 国产精品一区二区在线播放 | 最近中文字幕免费av | 亚洲国产精品电影 | 成年人在线观看视频免费 | 视频在线观看入口黄最新永久免费国产 | 91精品国产自产老师啪 | 911国产 | 日日爱夜夜爱 | 午夜 久久 tv | 天天草天天 | 在线观看中文字幕一区二区 | av资源免费观看 | 欧美吞精| 91精品久久久久久 | 精品久久久久久久久久久久久久久久久久 | 中文字幕一区二区在线播放 | 亚洲网久久 | 国产高清免费av | 亚洲精品小视频在线观看 | 精品国产成人在线影院 | 亚洲一级二级 | 中文字幕在线影视资源 | 日本久久精 | 波多野结衣精品 | 国产一区二区不卡视频 | 狠狠干.com| 日韩成人精品在线观看 | 国产综合91| 中文字幕在线不卡国产视频 | 国产成人高清在线 | 国产永久免费观看 | 西西www4444大胆视频 | 日韩精品无| 视频一区二区免费 | 日韩欧美亚洲 | 精品一区二区日韩 | 伊人中文网| 亚洲综合黄色 | 国产精品女同一区二区三区久久夜 | 国产成人无码AⅤ片在线观 日韩av不卡在线 | 亚洲专区一二三 | h动漫中文字幕 | 综合色中文 | 日韩av一区二区在线影视 | 成年人黄色大片在线 | 国产精品日韩 | 丁香色天天 | 高清色免费| 四虎海外影库www4hu | 中文字幕免费播放 | 久久精品爱视频 | 91成年人网站 | 国产精品欧美久久 | 日韩中文字幕亚洲一区二区va在线 | 亚洲国产中文字幕在线视频综合 | 99久久99久久精品国产片果冰 | 久久96国产精品久久99漫画 | 亚洲天堂网在线视频 | 久久深夜福利免费观看 | 婷婷激情综合 | 欧美成人免费在线 | 成人av在线一区二区 | 日韩精品中文字幕一区二区 | 国产精品a久久久久 | 免费视频二区 | 色综合色综合色综合 | 日韩成人不卡 | 99热这里有| 亚洲日本韩国一区二区 | 日韩欧美综合 | 日韩a免费 | 最近中文字幕国语免费高清6 | 国产精品久久艹 | 黄色国产成人 | 久久你懂得 | 五月婷婷六月丁香 | 久久精品香蕉 | 精品字幕 | 一级性视频 | 美女视频黄免费 | 999热视频| 国产 中文 日韩 欧美 | 黄色一二级片 | 日韩www在线| 日日躁天天躁 | 色综合色综合久久综合频道88 | 视频一区二区在线 | 亚洲精品1区2区3区 超碰成人网 | 欧美极品一区二区三区 | 欧美激情精品久久久久久 | 日韩在线观看第一页 | 97视频免费观看2区 亚洲视屏 | 免费精品视频在线观看 | 国产二区视频在线 | av国产在线观看 | 久久高清av | 九九热精品视频在线观看 | 五月天综合婷婷 | 国产福利av | 中文字幕一区二区三区乱码不卡 | 亚洲国产高清在线观看视频 | 在线va视频 | 免费a网| 色视频网站在线观看一=区 a视频免费在线观看 | 91亚洲视频在线观看 | www.久久久.com | 中文在线字幕免费观看 | 麻豆小视频在线观看 | av在线超碰 | 成人中文字幕av | 日韩 在线a | 波多野结衣在线观看视频 | 男女日麻批 | 日韩视频一区二区三区在线播放免费观看 | 欧美日韩国产一区二区三区 | 国产无区一区二区三麻豆 | 日韩欧美视频在线播放 | 国产一级91 | 国产亚洲无 | 久久一区精品 | 亚洲撸撸| 在线观看日韩精品视频 | 亚洲国产欧美一区二区三区丁香婷 | 狠狠狠色丁香综合久久天下网 | 99久久久国产精品免费99 | 日韩在线视频一区 | 国产一区二区精品 | 欧美日韩有码 | 啪啪精品 | 男女激情免费网站 | 日韩欧美一区二区三区免费观看 | 日本中文乱码卡一卡二新区 | 日p在线观看 | 国产亚洲精品v | 欧美日本中文字幕 | 黄污视频大全 | 一级黄色片在线观看 | 国产丝袜一区二区三区 | 久久久久久久久久久久久国产精品 | 成人黄色av免费在线观看 | 天天射综合网站 | 日本三级全黄少妇三2023 | 国产亚洲精品久久久久久久久久 | 日韩欧美亚州 | 成人一区二区三区中文字幕 | 日韩福利在线观看 | 国产精品无av码在线观看 | 天天爱天天射天天干天天 | 国产伦理久久精品久久久久_ | 伊人久久国产精品 | 91在线色| 免费黄色激情视频 | 西西4444www大胆视频 | 国产在线精品一区二区三区 | 成 人 黄 色 视频 免费观看 | 91精品国产综合久久福利 | 日韩在线小视频 | 久久久久久久久久久免费视频 | 免费在线观看一区 | 网站在线观看你们懂的 | 91在线porny国产在线看 | 人人爽人人爽人人片av | 亚洲黄色网络 | 九九九热 | 久久伊人爱 | 亚洲综合少妇 | 成人av电影免费在线播放 | 久久久久久国产精品亚洲78 | 91免费的视频在线播放 | 99视频精品 | 日韩免费在线观看网站 | 99国产免费网址 | 91久久精品一区二区二区 | 在线亚洲激情 | av中文字幕网址 | 精精国产xxxx视频在线播放 | 亚洲天堂社区 | 天天综合入口 | 99免费在线视频 | 在线视频 亚洲 | 特级西西444www大胆高清无视频 | 成年性视频| 成人午夜电影在线播放 | 在线视频精品 | 免费在线成人av | 国产精品久久久久婷婷二区次 | 色视频网站在线 | 免费看久久 | 欧美黑吊大战白妞欧美 | av免费观看网址 | 狠狠伊人| 久久一线 | 日韩精品在线免费播放 | 亚洲精品乱码久久久久久久久久 | av在线精品 | 久久久久一区二区三区 | 成人全视频免费观看在线看 | 日本99久久 | 久久爽久久爽久久av东京爽 | 又黄又爽的免费高潮视频 | 五月天中文字幕 | 九九热中文字幕 | 欧美天天综合 | 日本黄色免费看 | 欧美a影视 | 精品国模一区二区 | 99热日本 | 国产第一页在线观看 | 天天色天天艹 | 久久看视频| 色视频在线观看免费 | 四虎影视欧美 | 国产色视频一区 | 欧美日韩不卡在线 | 国产精品美女久久久久aⅴ 干干夜夜 | 欧美另类一二三四区 | 爱色婷婷 | 精品日韩中文字幕 | 欧美成人播放 | 激情视频国产 | 国产一区二区在线影院 | av大全在线看 | 永久黄网站色视频免费观看w | 99人久久精品视频最新地址 | 在线最新av | 日韩av一卡二卡三卡 | 粉嫩av一区二区三区入口 | 亚洲精品国偷拍自产在线观看蜜桃 | 日韩高清片 | 久久草在线视频国产 | 狠狠狠狠狠狠狠狠 | 免费网站黄色 | 在线草 | 韩国精品一区二区三区六区色诱 | 亚洲精品麻豆 | 99国产精品免费网站 | 97精品国自产拍在线观看 | 欧美日韩久久不卡 | 午夜av网站 | 久久国内精品 | 在线国产日韩 | 欧美激情视频在线观看免费 | 欧美精品久久久久久久久免 | 亚洲天堂网站视频 | 免费精品 | 中文字幕免费观看全部电影 | 综合色婷婷 | 中文在线免费观看 | 二区三区视频 | 色综合久久久 | 亚洲国产av精品毛片鲁大师 | 国产精品久久在线 | 国产999| 色综合网在线 | 午夜色婷婷 | 在线播放一区 | 91完整视频 | 99热99re6国产在线播放 | 91麻豆精品国产91久久久更新时间 | 国产精品自在线 | 中文字幕一区二区三区乱码不卡 | 精品久久久久国产免费第一页 | 成人免费看视频 | 亚洲午夜精品久久久久久久久久久久 | 国产成人av | 亚洲欧美日韩一二三区 | 国内免费久久久久久久久久久 | 韩国精品一区二区三区六区色诱 | 亚洲在线成人精品 | 亚洲高清视频在线观看免费 | 国产精品人人做人人爽人人添 | 欧美日韩亚洲在线观看 | 97操碰| 久久99亚洲网美利坚合众国 | 一区三区视频 | 91视频免费| 日韩大片免费观看 | 欧美一级黄大片 | 日韩高清免费无专码区 | 99精品免费久久久久久久久 | 91在线文字幕 | 国产精品国产三级国产aⅴ入口 | 亚洲视频免费在线 | 日韩三级视频在线看 | 久久久伊人网 | 免费成人av在线看 | 九九国产精品视频 | 欧美日韩一区二区三区视频 | 玖玖玖在线观看 | 在线免费观看羞羞视频 | 亚洲一区日韩在线 | 92av视频| 人人看97 | 91精品国产福利 | 欧美性做爰猛烈叫床潮 | 国产一级视频 | 美女激情影院 | 在线免费国产视频 | 成人av影视在线 | 国产成人精品久久久久蜜臀 | 91亚瑟视频| 欧美成人性网 | 精品久操| 中文字幕一区二区三区在线视频 | 69视频永久免费观看 | 久久综合狠狠综合久久狠狠色综合 | 97在线看片 | 97在线精品国自产拍中文 | 久久综合亚洲鲁鲁五月久久 | 丝袜美女在线观看 | 午夜美女福利直播 | 成人h视频在线播放 | 91专区在线观看 | 国产成人精品综合久久久 | 国内偷拍精品视频 | 国产精品网红福利 | 91色网址| 一区二区理论片 | 亚洲精品456在线播放第一页 | 国产一区成人 | 欧美一区中文字幕 | 国产精品久久网 | 亚洲精品视频免费观看 | 久草在线网址 | 在线观看日本高清mv视频 | 开心色激情网 | 友田真希av | 精品久久国产一区 | 亚洲成人av电影在线 | 日韩视频免费 | www.久久爱.cn | 成人在线观看免费 | 91 在线视频 | av丝袜制服 | 色诱亚洲精品久久久久久 | 久久久久久久久久国产精品 | 香蕉在线视频播放网站 | 国产成人一区二区在线观看 | 日韩高清av | 在线观看日韩中文字幕 | 91在线公开视频 | 久久综合久色欧美综合狠狠 | 亚洲精品乱码久久久久久9色 | 久久亚洲精品国产亚洲老地址 | 日本三级全黄少妇三2023 | 欧美性色综合 | av大全免费在线观看 | 91大片成人网 | 欧洲亚洲精品 | 国产亚洲小视频 | 午夜婷婷网 | 精品视频国产 | 91亚洲国产 | 人成在线免费视频 | 国产精品久久久久久影院 | 一级黄色视屏 | 亚洲精品资源在线 | 亚洲涩涩涩| 中文字幕 国产视频 | 91成人精品在线 | 五月婷在线播放 | 亚洲综合激情 | 97网| 天堂av免费| 婷婷色婷婷 | 欧美日韩一区二区三区在线观看视频 | 免费视频 你懂的 | 亚洲国产视频a | 亚洲欧洲精品一区二区精品久久久 | 久久96国产精品久久99漫画 | h文在线观看免费 | 国产精品成人一区二区三区吃奶 | 国产精久久久久久久 | 亚洲3级| 国产成人精品区 | 久久99热精品 | 免费看片亚洲 | 中文字幕在线看视频国产中文版 | 免费在线播放av电影 | 日日夜夜艹| 久久视频这里有久久精品视频11 | 免费在线国产 | 天天操网 | 国产一区在线视频播放 | 免费av在线播放 | 97色在线视频| 欧美在线视频二区 | 91久久影院| 精品福利视频在线观看 | 91精品天码美女少妇 | 中文字幕在线有码 | 婷婷激情影院 | 五月天精品视频 | 亚洲成人动漫在线观看 | 中文字幕免费高清 | 一区二区三区久久精品 | 亚洲精品日韩一区二区电影 | 中文字幕在线观看视频一区二区三区 | 精产嫩模国品一二三区 | 免费网站观看www在线观看 | 欧美在线观看视频一区二区三区 | 99热这里只有精品国产首页 | 久久久久久伊人 | 韩日av一区二区 | 精品一区三区 | 国产美女精品在线 | 欧美精品免费视频 | 免费污片 | 欧美成人精品在线 | 久草在线最新免费 | 91久久久久久久一区二区 | 国内精品久久久久久久久久久 | 国产中文字幕网 | 免费十分钟 | 亚州成人av在线 | 色丁香婷婷 | 国产又粗又猛又黄又爽视频 | 亚州国产精品视频 | 日韩欧美一区二区不卡 | 天天干天天操天天爱 | 综合久久五月天 | 美女久久久久久久久久久 | 免费视频91 | 午夜影视一区 | 国产精品久久久久久麻豆一区 | 99精品热视频只有精品10 | 四虎影视成人永久免费观看亚洲欧美 | 国产精品色在线 | 亚洲精品av在线 | 麻豆影音先锋 | 亚州视频在线 | 99久久激情| 天天操天天射天天爱 | 亚洲乱码在线观看 | 久久噜噜少妇网站 | 激情久久伊人 | 国产资源在线免费观看 | 亚洲国产日韩在线 | 青春草免费在线视频 | 亚洲国产精品电影在线观看 | 午夜影视剧场 | 色综合久久88色综合天天人守婷 | 国产精品一区免费看8c0m | 日韩欧美在线高清 | 高清不卡一区二区在线 | 久久综合给合久久狠狠色 | 婷婷亚洲五月 | 最新国产精品久久精品 | 精品国产成人av在线免 | 国产破处在线视频 | 国产福利免费看 | 天天干天天做 | 国产婷婷精品 | 久草在线视频免赞 | 中文字幕免费高清在线观看 | 999久久国产精品免费观看网站 | 97视频人人澡人人爽 | 在线av资源| 欧美日韩一区二区在线 | 亚洲视频在线免费看 | 免费黄色a级毛片 | 看黄色.com | 亚洲精品视频久久 | 日韩精品视频第一页 | 亚洲视频在线观看网站 | 久久国产精品久久精品国产演员表 | 久久精视频 | 99热精品视 | 91在线视频免费观看 | 最近高清中文字幕在线国语5 | 色吊丝在线永久观看最新版本 | 久久精品这里都是精品 | 欧美日韩精品电影 | 在线观看一级 | 99精品久久久久久久久久综合 | 中文字幕你懂的 | 99久久精品日本一区二区免费 | 欧美久久久久久久久久 | 亚洲亚洲精品在线观看 | 久久久免费观看 | 国产日韩精品一区二区在线观看播放 | 色综合天天做天天爱 | 久久久久国产一区二区三区四区 | 亚洲人成网站精品片在线观看 | 亚洲色图 校园春色 | 亚洲综合网站在线观看 | 激情六月婷婷久久 | 日韩欧美大片免费观看 | 久久国产网站 | 午夜精品福利影院 | 九色视频网址 | 日韩a在线观看 | 99精品在这里 | 免费在线观看成人 | 91视频免费看 | 成人毛片一区 | 最近2019好看的中文字幕免费 | av在线免费播放网站 | 91久久久久久国产精品 | 精品视频免费 | 国产精品久久久久av福利动漫 | 免费a一级 | 免费看黄的 | av字幕在线| 国产精品免费一区二区三区 | 97超碰人人澡人人爱 | 在线观看国产成人av片 | 欧美日韩性视频在线 | 成人免费xxxxxx视频 | 四虎影视成人精品 | 久久久国产网站 | 欧美日韩性视频在线 | 欧美视屏一区二区 | 国产免费观看av | 丁香婷婷激情国产高清秒播 | 国产精品久久久久9999吃药 | 中文字幕区 | 97超碰.com| 久久久九色精品国产一区二区三区 | 深夜福利视频一区二区 | 日日爱网址 | 免费av试看 | av免费观看网站 | 日日爽日日操 | 麻豆传媒视频观看 | 免费av看片 | 国产精品美女久久久久久 | 国产综合精品一区二区三区 | 999久久久精品视频 日韩高清www | 亚洲国产精品电影 | 黄色成人毛片 | 日韩在线视频网站 | 国产精品av免费 | 亚欧日韩成人h片 | 99久热在线精品视频成人一区 | 99超碰在线观看 | 一本色道久久综合亚洲二区三区 | 国产 欧美 日本 | 免费看黄在线观看 | 国产无遮挡又黄又爽在线观看 | 亚洲精品乱码久久久久 | 91视频 - 114av | 国产色资源 | 五月综合色 | 午夜性生活片 | 黄免费在线观看 | 亚洲人人射 | 成人在线观看免费 | 国产最新网站 | 激情深爱五月 | 婷婷在线视频观看 | 国产一区免费 | 亚洲成人999| 日韩欧美69 | 狠狠狠狠狠狠狠狠干 | 00av视频 | 亚洲一区视频在线播放 | 狠狠久久综合 | 黄色网址国产 | 91色视频 | 亚洲电影在线看 | 亚洲日韩中文字幕 | 波多野结衣一区二区三区中文字幕 | 久久97精品| 欧美成人精品xxx | 久久久久国产a免费观看rela | 国产一区欧美日韩 | 国产剧情一区二区在线观看 | 96av在线视频 | 久久久久成人免费 | 国产福利免费在线观看 | 24小时日本在线www免费的 | 日日爽天天操 | 日韩一区二区三区免费电影 | 国产亚洲成av人片在线观看桃 | 国内毛片毛片 | 91精品影视| 少妇性色午夜淫片aaaze | 麻豆久久久 | 久久电影网站中文字幕 | 午夜资源站 | 人人网人人爽 | www.国产毛片| 日本xxxx.com| 免费a v观看 | 中日韩男男gay无套 日韩精品一区二区三区高清免费 | 日韩精选在线 | 国产不卡精品视频 | 一级a性色生活片久久毛片波多野 | 国产做a爱一级久久 | 中文字幕视频免费观看 | 亚洲精品国产拍在线 | 国内精品在线一区 | 日本女人b| 99久久超碰中文字幕伊人 | 国产精品亚州 | 美女视频久久黄 | 在线观看日韩中文字幕 | 天天天天爽 | 97精品国产97久久久久久粉红 | 精品久久久久久久 | 亚洲理论电影 | www.日日日.com | 中文字幕丝袜 | 亚洲乱码在线 | 精品久久久久久国产91 | 免费日韩一区二区 | 视频二区 | 日韩中文在线播放 | 激情av资源 | 99热最新网址 | 日本中文字幕在线免费观看 | 亚洲va欧美va人人爽春色影视 | 国产免费黄视频在线观看 | 在线观看精品 | 最新日韩在线观看 | 麻豆va一区二区三区久久浪 | 蜜臀久久99精品久久久久久网站 | 一区二区三区高清不卡 | av一本久道久久波多野结衣 | 成人在线一区二区三区 | 91网站免费观看 | 久久韩国免费视频 | 亚洲综合色视频 | 日本韩国精品一区二区在线观看 | 国产精品18videosex性欧美 | 国产成人精品一区二区三区在线观看 | 国产乱码精品一区二区蜜臀 | 中文字幕乱码一区二区 | 91免费高清视频 | 天天看天天干天天操 | 成人av免费网站 | 久久国产精品视频 | 一区二区三区四区久久 | 国产精品福利久久久 | 亚洲国产欧美在线人成大黄瓜 | 欧美日韩国产在线 | 国产资源在线视频 | 超碰97在线人人 | 97精品国产一二三产区 | 500部大龄熟乱视频使用方法 | 99久久精品国产系列 | 97免费在线观看视频 | 精品亚洲欧美无人区乱码 | 在线观看视频你懂的 | 久久超碰在线 | 久久女同性恋中文字幕 | 成人一区二区三区在线 | www.香蕉| 国产日韩精品一区二区三区在线 | .国产精品成人自产拍在线观看6 | 国产精品精品视频 | 69国产精品视频 | 激情电影影院 | www.神马久久| 91中文字幕网 | 超碰国产97 | 97电影手机 | 狠狠黄| 99久久99热这里只有精品 | 日本公妇在线观看高清 | 欧美a级在线免费观看 | 天天爽夜夜操 | 婷婷综合激情 | 免费高清在线观看成人 | av片一区| 欧美成人在线免费 | 在线看成人av | 五月婷婷六月综合 | 91av蜜桃| 美女福利视频在线 | 久久久一本精品99久久精品66 | 欧美射射射| 丁香六月天婷婷 | 久草在线官网 | 国产高清成人av | 欧美日本不卡高清 | 最近2019好看的中文字幕免费 | a v在线视频 | 国产精品九九久久久久久久 | 国产夫妻av在线 | 91视频91蝌蚪 | 国产高清精品在线观看 | 中文字幕精品一区久久久久 | 亚洲美女视频在线观看 | 亚洲影视资源 | 精品国产乱码一区二 | 日韩av专区 | 久久国产成人午夜av影院宅 | 久久久精品欧美一区二区免费 | 亚洲黄色免费观看 | 丁香激情综合久久伊人久久 | 一本到视频在线观看 | 色婷婷狠狠干 | 伊人精品在线 | 亚洲国产精久久久久久久 | 亚洲精品乱码久久久久 | 狠狠色伊人亚洲综合网站野外 | 日本成址在线观看 | 国产呻吟在线 | 国产破处精品 | 国产精品毛片网 | 一区二区三区精品在线 | 在线观看成年人 | 在线中文字幕一区二区 | 最新午夜电影 | 五月婷婷丁香在线观看 | 97超视频免费观看 | 91 在线视频 | 视频在线一区二区三区 | 麻豆视频在线免费看 | 国产精品第72页 | 91黄色影视| 国产午夜三级一区二区三 | 久久久久伊人 | av视屏在线播放 | 在线免费av网站 | 97在线免费| 日韩免费视频在线观看 | 中文字幕一区二区三区久久蜜桃 | 国产一级免费播放 | 久久免费99 | 婷婷精品在线 | 狠狠狠狠狠狠狠狠 | 亚洲精品456在线播放第一页 | 精品视频免费观看 | 日日操天天爽 | 欧美日韩亚洲一 | 激情婷婷欧美 | 91成人在线观看喷潮 | 天天躁日日躁狠狠 | 国产亚洲精品久久久久久久久久久久 | 国产在线视频一区 | 久久免费在线观看视频 | 国产二区电影 | h动漫中文字幕 | 在线观看国产日韩 | 91日韩精品视频 | 欧美-第1页-屁屁影院 | 97av精品 | 欧美日韩一二三四区 | 国产精品久久久久久久久久白浆 | 成人av免费在线播放 | 黄色小说视频在线 | 国产在线视频导航 | 久久99久久久久 | 成人国产精品一区二区 | 超碰资源在线 | 中文字幕一区二区三区精华液 | 亚洲日本精品视频 | 97电院网手机版 | 2021国产精品视频 | 久久99网站 | 午夜三级理论 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 人人爽人人搞 | 国产最新精品视频 | 国产色视频一区 | 国产亚洲人成网站在线观看 | 在线色视频小说 | 91丨九色丨蝌蚪丨对白 | 最近免费观看的电影完整版 | 啪啪肉肉污av国网站 | 91福利在线导航 | 免费观看xxxx9999片 | 精品一区二区三区久久 | 国产又粗又猛又黄又爽 | 免费黄色特级片 | 日韩成人邪恶影片 | 国产精品九九热 | 精品国产_亚洲人成在线 | 久久天天躁狠狠躁亚洲综合公司 | 九九九在线 | 成人在线观看影院 | 久久国产片 | 天天色天天操综合网 | 91亚洲精品久久久中文字幕 | 黄av在线| 日韩三级视频在线观看 | 成年人网站免费在线观看 | a天堂一码二码专区 | 天天综合色 | 97超碰人人在线 | 国产精久久久久久久 | 99热这里只有精品在线观看 | 久色免费视频 | 日日天天狠狠 | 国产亚洲精品久久久久久网站 | wwwww.国产 | 91精品欧美一区二区三区 | 国产美女在线免费观看 | 精品一区二区亚洲 | 精品久久久影院 | 99九九99九九九视频精品 | 成人影视免费 | 一区二区三区在线免费 | 国产一区二区在线免费 | 欧美日韩国产在线 | 99在线视频免费观看 | 中文字幕91视频 | 天天操天天艹 | 亚洲最大av在线播放 | 欧美性爽爽 | 欧美日韩不卡一区 | 丁香视频在线观看 | 91在线日韩 | 欧美日韩一区二区久久 | 欧美成人亚洲成人 | 久久精品艹 | 手机看片 | www.xxxx欧美 | 国产婷婷视频在线 | 丁香六月激情 | 欧美精品在线观看免费 | av中文字幕在线观看网站 | 国产高清av免费在线观看 | 狠狠干中文字幕 | 在线免费观看的av | 日本婷婷色 | 久久福利在线 | 91亚洲精品久久久蜜桃 | 国内成人精品2018免费看 | 中文字幕在线视频一区 | 中文字幕丝袜一区二区 | 九九九在线观看 | 精品亚洲男同gayvideo网站 | 国产精品久久久久久久妇 | 精品久久中文 | 国产精品入口传媒 | 亚洲综合精品在线 | 久久人人爽人人人人片 | 97偷拍在线视频 | wwwwww色| 亚洲第一区在线观看 | 日韩精品一区二区免费 | 日日夜夜狠狠操 | 久久国产色 | 免费午夜视频在线观看 | 日韩网站免费观看 | 粉嫩av一区二区三区四区 | 一区二区激情 | 国产一区二区三精品久久久无广告 | 丁香视频五月 | 久久激情小视频 | 超级av在线 | 99精品观看 | 中文在线字幕免费观看 | 免费h在线观看 | 亚洲另类视频在线 | 国产精品久久网站 | 久久一精品 |