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

隨筆-162  評論-223  文章-30  trackbacks-0
 
   nginx的域名解析器使用已連接udp(收發前先調用ngx_udp_connect)發送dns查詢、接收dns響應,如上篇tcp異步連接所講,iocp需要先投遞udp的接收操作,才能引發接收完成的事件,因此要對域名解析器和udp異步接收作些改進。

發送后投遞
    dns查詢由ngx_resolver_send_query函數實現,定義在core/ngx_resolver.c中。
 1static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
 2{
 3    
 4     if (rn->naddrs == (u_short) -1{
 5        n = ngx_send(uc->connection, rn->query, rn->qlen);
 6    
 7  }

 8
 9#if (NGX_HAVE_INET6)
10  if (rn->query6 && rn->naddrs6 == (u_short) -1{
11      n = ngx_send(uc->connection, rn->query6, rn->qlen);
12    
13  }

14#endif
15
16#if (NGX_WIN32) 
17    if (ngx_event_flags & NGX_USE_IOCP_EVENT){
18        uc->connection->read->ready = 1;
19        ngx_resolver_read_response(uc->connection->read);
20}

21#endif
22
23  return NGX_OK;
24}
    當nginx用于代理連接上游服務器前,要先解析域名,首次調用鏈為:ngx_http_upstream_init_request->ngx_resolver_name->ngx_resolver_name_locked->ngx_resolver_send_query;若5s(單次超時)后還沒收到dns響應,則再發送1次查詢,調用鏈為:ngx_resolver_resend_handler->ngx_resolver_resend->ngx_resolver_send_query,如此反復,直到收到響應或30s(默認總超時)后不再發送查詢。它調用ngx_send發送dns查詢,16行~21行代碼為筆者添加,ngx_resolver_read_response函數用于接收并分析dns響應報文,它會調用到下面的ngx_udp_overlapped_wsarecv函數。

異步接收
   由ngx_udp_overlapped_wsarecv函數實現,定義在os/win32/ngx_udp_wsarecv.c中。
 1ssize_t ngx_udp_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size)
 2{
 3    int             flags, rc;
 4    WSABUF          wsabuf;
 5    ngx_err_t       err;
 6    ngx_event_t    *rev;
 7    WSAOVERLAPPED  *ovlp;
 8    u_long             bytes;
 9    
10    rev = c->read;
11    
12    if (!rev->ready) {
13      ngx_log_error(NGX_LOG_ALERT, c->log, 0"ngx_udp_overlapped_wsarecv second wsa post");
14      return NGX_AGAIN;
15  }

16    
17  if (rev->complete) {
18   if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
19       if (rev->ovlp.error && rev->ovlp.error != ERROR_MORE_DATA{
20           ngx_connection_error(c, rev->ovlp.error, "ngx_udp_overlapped_wsarecv() failed");
21           return NGX_ERROR;
22       }

23   }

24   
25   rev->complete = 0;
26  }

27     
28    ovlp = NULL;
29    wsabuf.buf = (CHAR *) buf;
30    wsabuf.len = (ULONG) size;
31    flags = 0;
32    
33retry:    
34    rc = WSARecv(c->fd, &wsabuf, 1, (DWORD*)&bytes, (LPDWORD)&flags, ovlp, NULL);
35        
36    if (rc == -1{
37         rev->ready = 0;
38         err = ngx_socket_errno;
39    
40       if (err == WSA_IO_PENDING) {
41             return NGX_AGAIN;
42         }

43    
44       if (err == WSAEWOULDBLOCK) {
45           if (ngx_event_flags & NGX_USE_IOCP_EVENT) {                
46                 rev->ovlp.type = NGX_IOCP_IO;
47                 ovlp = (WSAOVERLAPPED *)&rev->ovlp;
48                 ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));
49                
50                 wsabuf.buf = NULL;
51                 wsabuf.len = 0;
52                 flags = MSG_PEEK;
53                
54                goto retry;            
55            }

56            
57            return NGX_AGAIN;            
58        }

59            
60        ngx_connection_error(c, err, "ngx_udp_overlapped_wsarecv() failed");    
61        rev->error = 1;
62    
63        return NGX_ERROR;
64    }

65    
66    if ((ngx_event_flags & NGX_USE_IOCP_EVENT) && ovlp) {
67        rev->ready = 0;
68        return NGX_AGAIN;
69    }

70    
71    return bytes;
72}
   先以非阻塞方式接收,若發生WSAWOULDBLOCK錯誤,則使用MSG_PEEK標志投遞一個0字節的重疊接收操作,當dns響應返回時發生完成事件,會再次進入ngx_resolver_read_response而調用到該函數,此時rev->complete為1,rev->ovlp.error為ERROR_MORE_DATA(GetQueuedCompletionStatus返回的錯誤),由于使用了MSG_PEEK,因此數據還在接收緩沖區中,要忽略ERROR_MORE_DATA而繼續接收,這時就能成功了。不管WSARecv返回WSA_IO_PENDING錯誤還是成功,iocp都會得到完成通知,所以這里當重疊操作投遞成功時,返回NGX_AGAIN,便于在回調內統一處理。
posted @ 2015-06-25 17:01 春秋十二月 閱讀(6265) | 評論 (0)編輯 收藏
   iocp是Windows NT操作系統的一種高效IO模型,對應于Linux中的epoll和FreeBSD中的kqueue,nginx對ske(select、kqueue和epoll的首寫字母組合)的支持很好,但截止到1.6.2版本,還不支持iocp。由于ske都是反應器模式,即先注冊IO事件,當IO事件發生(讀寫通知)時,在其回調內主動調用API來讀或寫數據;而iocp是前攝器模式,要先投遞IO操作,才能引發IO事件(完成通知)的發生,在其回調內數據已被動由操作系統讀或寫完成。因此,iocp的特點決定了nginx對它的支持與ske有所不同。通過hg clone http://hg.nginx.org/nginx下載的nginx源代碼,雖然實現了iocp事件模塊、異步接受連接、部分異步讀寫,但根本不能正常工作,而且不支持異步連接和SCM服務控制,筆者在參考ske模塊的實現基礎上,改進支持了如下特性:
      1. 異步接受連接時的負載均衡
      2. 正反向代理的異步連接
      3. 異步聚合讀寫
      4. 域名解析時的UDP異步接收
      5. 異步文件傳輸
      6. SCM服務控制
   由于2、4、6均為原創,其它幾點的思路皆源于ske模塊的實現(只是平臺API不同),因此本文先闡述異步連接的實現。為了兼容select事件模塊,所有iocp相關的代碼使用NGX_HAVE_IOCP宏和(或)NGX_USE_IOCP_EVENT標志包圍,其中NGX_HAVE_IOCP宏用于條件編譯,在WIN32平臺下,定義為1;當選擇的事件模塊為iocp時,全局變量ngx_event_flags才包含NGX_USE_IOCP_EVENT標志。

異步連接對端
   由ngx_event_connect_peer函數(這里省去了與異步連接無關的代碼)實現,定義在event/ngx_event_connect.c中,因為connect不支持異步連接事件的完成通知,所以要使用擴展API ConnectEx。 
 1ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc)
 2{
 3    int                rc;
 4    ngx_int_t          event;
 5    ngx_err_t          err;
 6    ngx_uint_t         level,family;
 7    ngx_socket_t       s;
 8    ngx_event_t       *rev, *wev;
 9    
10    s = ngx_socket(family = pc->sockaddr->sa_family, SOCK_STREAM, 0);
11              
12    #if (NGX_HAVE_IOCP)
13    if((pc->local==NULL||pc->local->sockaddr->sa_family != family) 
14        && (ngx_event_flags & NGX_USE_IOCP_EVENT)){
15        if(ngx_iocp_set_localaddr(pc->log,family,&pc->local) != NGX_OK)
16            goto failed;    
17    }

18    #endif
19       
20    
21    #if (NGX_HAVE_IOCP)
22    if(ngx_event_flags&NGX_USE_IOCP_EVENT){        
23        LPWSAOVERLAPPED   ovlp;
24        ovlp = (LPWSAOVERLAPPED)&wev->ovlp;
25        ngx_memzero(ovlp,sizeof(WSAOVERLAPPED));
26        wev->ovlp.type = NGX_IOCP_CONNECT;
27        rc = ngx_connectex(s,pc->sockaddr,pc->socklen,NULL,0,NULL,ovlp) ? 0 : -1;
28    
29    }
else
30        rc = connect(s, pc->sockaddr, pc->socklen);
31    #else
32      rc = connect(s, pc->sockaddr, pc->socklen);
33    #endif
34    
35    if (rc == -1{
36        err = ngx_socket_errno;
37        if (err != NGX_EINPROGRESS
38    #if (NGX_WIN32)
39        /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
40        && err != NGX_EAGAIN
41    #if (NGX_HAVE_IOCP)
42        && err != WSA_IO_PENDING
43    #endif
44    #endif
45            ){
46            
47            ngx_log_error(level, c->log, err, "connect() to %V failed", pc->name);
48            ngx_close_connection(c);
49            pc->connection = NULL;
50          
51            return NGX_DECLINED;
52        }

53    }

54    
55}
   調用ConnectEx前要先bind本地地址,不然發生WSAEINVAL錯誤;由于域名解析可能返回IPv6記錄,導致創建本地套接字的地址族為AF_INET6,因此bind時需要匹配IPv6地址,不然發生WSAEFAULT錯誤,導致nginx返回Internal Server Error錯誤給前端,因此綁定前要調用ngx_iocp_set_localaddr設定正確的本地地址,當且僅當pc->local為空或地址族不匹配時。

本地初始化與設定
   支持IPv6,實現在event/modules/ngx_iocp_module.c。
   地址變量定義如下。
1static struct sockaddr_in  sin;
2#if (NGX_HAVE_INET6)
3static struct sockaddr_in6  sin6;
4#endif
5static ngx_addr_t           local_addr;
   sin對應IPv4,sin6對應IPv6,作為bind的套接字本地地址。

   sin和sin6在啟動iocp事件模塊時調用ngx_iocp_init初始化。   
 1static ngx_int_t ngx_iocp_init(ngx_cycle_t *cycle, ngx_msec_t timer)
 2{
 3    
 4  sin.sin_family = AF_INET;
 5  sin.sin_port = 0;
 6  sin.sin_addr.s_addr = INADDR_ANY;
 7    
 8#if (NGX_HAVE_INET6)
 9    sin6.sin6_family = AF_INET6;
10    sin6.sin6_port = 0;
11    sin6.sin6_addr = in6addr_any;
12#endif
13    
14  local_addr.name.len = sizeof("INADDR_ANY"- 1;
15  local_addr.name.data = (u_char *)"INADDR_ANY";    
16    
17}
   不論IP地址或端口,都指定為0,表示由系統自動分配出口IP地址和未占用的端口。

   本地設定由ngx_iocp_set_localaddr實現。
 1ngx_int_t ngx_iocp_set_localaddr(ngx_log_t *log, in_port_t family, ngx_addr_t **local)
 2{
 3    struct sockaddr *sa;
 4    socklen_t len;
 5    
 6    if(AF_INET == family){            
 7        sa = &sin;
 8        len = sizeof(struct sockaddr_in);        
 9    }

10#if (NGX_HAVE_INET6)
11    else if(AF_INET6 == family){
12        sa = &sin6;
13        len = sizeof(struct sockaddr_in6);
14    }

15#endif
16    else{
17        ngx_log_error(NGX_LOG_ALERT, log, 0"not supported address family");
18        return NGX_ERROR;        
19    }

20
21    local_addr.sockaddr = sa;
22    local_addr.socklen = len;
23    *local = &local_addr;
24
25    return NGX_OK;
26}
   對于除IPv4和IPv6外的協議族,則記錄一個錯誤日志。必要時也可擴展支持其它的協議族,例如NetBIOS(對應地址族為AF_NETBIOS),但要看ConnectEx是否支持。
posted @ 2015-06-24 17:02 春秋十二月 閱讀(7675) | 評論 (1)編輯 收藏
   ICMP在IP系統間傳遞差錯和管理報文,是任何IP系統必須實現的組成部分。Linux 2.6.34中ICMP模塊的實現在linux/icmp.h,net/icmp.h和ipv4/icmp.c中,導出了icmp_err_convert數組和icmp_send函數,供其它網絡子系統使用。在其它網絡子系統中,當檢測到錯誤時,調用icmp_send產生并發送相應的ICMP差錯消息到源主機;當源主機收到ICMP不可達差錯消息,傳遞到原始套接字和傳輸層,而它們使用icmp_err_convert把對應的消息代碼轉換成套接字層比較容易理解的錯誤代碼。在內核空間中可發送的ICMP消息包括查詢應答和差錯報文,下面總結了產生這兩類消息的網絡子系統(及函數)與錯誤轉換。


應答消息
   應答消息由ICMP模塊的內部函數icmp_reply而非icmp_send發送。根據RFC1122 3.2.2.9規范, 除非一個主機作為地址掩碼代理,否則不能發送回復,這對應ICMP的icmp_address實現為空,因此上表沒有列出地址掩碼應答項(內核符號為ICMP_ADDRESSREPLY)。

差錯消息
   差錯消息由中間路由器或目的主機產生,當數據報不能成功提交給目的主機時。從上表可見,在IP層的接收、本地處理、轉發和輸出各過程中,都可能產生差錯消息;在傳輸層如果對應的端口沒有打開,那么UDP會產生ICMP端口不可達差錯,而TCP則會使用自己的差錯處理機制發送一個RST復位包,這也是上表沒有列出TCP子系統的原因。對于重定向差錯,由ICMP模塊的icmp_redirect調用ip_rt_redirect更新路由;其它差錯則由icmp_unreach處理。


錯誤轉換
   第2列為icmp_err_convert數組索引,第4列也就是調用socket API出錯時返回的errno,最后1列為icmp_err_convert中的fatal成員取值,0表示非致命錯誤,1表示致命錯誤,需要報告給用戶進程。錯誤轉換會被RAW的raw_err、TCP的tcp_v4_err和UDP的udp_err用到,對于ICMP_DEST_UNREACH類型的差錯,使用上表轉換;ICMP_SOURCE_QUENCH類型的忽略不處理;ICMP_PARAMETERPROB類型的轉換成EPROTO(協議錯誤);ICMP_TIME_EXCEEDED類型的轉換成EHOSTUNREACH。
   在這要注意,從ICMP_PORT_UNREACH到ECONNREFUSED的轉換,不適用于TCP,原因已在上節說明;而對于UDP的未連接套接字,如果主機在線而端口沒打開,調用sendto得不到ECONNREFUSED錯誤,但recvfrom會阻塞,這是因為雖然內核收到了ICMP差錯,但沒上報給應用進程。盡管如此,如果想得到ECONNREFUSED錯誤,那么可以寫個ICMP守護進程,應用進程先把它的套接字描述符通過unix域套接口傳遞到ICMP守護進程,而守護進程使用raw socket來接收ICMP差錯,再發給應用進程。


發送限速
   不論一般差錯消息還是重定向差錯消息,發送限速針對的都是特定目標主機。
   一般限速
   在使用icmp_send發送差錯消息(PMTU消息除外)時,為減少網絡擁塞而限制了發送的速率,限速由xrlim_allow函數實現,定義在ipv4/icmp.c中。
 1#define XRLIM_BURST_FACTOR 6
 2int xrlim_allow(struct dst_entry *dst, int timeout)
 3{
 4    unsigned long now, token = dst->rate_tokens;
 5    int rc = 0;
 6
 7    now = jiffies;
 8    token += now - dst->rate_last;
 9    dst->rate_last = now;
10    if (token > XRLIM_BURST_FACTOR * timeout)
11        token = XRLIM_BURST_FACTOR * timeout;
12    if (token >= timeout) {
13        token -= timeout;
14        rc = 1;
15    }

16    dst->rate_tokens = token;
17    return rc;
18}
   dst為目標路由緩存,timeout為允許發送的超時(單位為jiffies),dst->rate_tokens記錄令牌的個數,當令牌個數不小于timeout時,則減少timeout并允許發送一個消息;反之則不能發送,需等到令牌個數累積到大于timeout時才能發送,但是不能無限大,否則就會導致在一個可能很短的timeout內,發送遠多于6個的消息,引起ICMP風暴,所以這里限制了令牌的最大值為XRLIM_BURST_FACTOR*timeout即6倍的超時,也就是說在一個timeout內,最多能發送6個差錯消息。 
  
   重定向限速
   路由子系統使用ip_rt_send_redirect來發送重定向消息,定義在ipv4/route.c中,該函數內部調用icmp_send實現,在它的限速基礎上,使用指數回退算法控制發送速率。
 1void ip_rt_send_redirect(struct sk_buff *skb)
 2{
 3    struct rtable *rt = skb_rtable(skb);
 4    
   
 5
 6    /* No redirected packets during ip_rt_redirect_silence;
 7     * reset the algorithm.
 8     */

 9    if (time_after(jiffies, rt->u.dst.rate_last + ip_rt_redirect_silence))
10        rt->u.dst.rate_tokens = 0;
11
12    /* Too many ignored redirects; do not send anything
13     * set u.dst.rate_last to the last seen redirected packet.
14     */

15    if (rt->u.dst.rate_tokens >= ip_rt_redirect_number{
16        rt->u.dst.rate_last = jiffies;
17        return;
18    }

19
20    /* Check for load limit; set rate_last to the latest sent
21     * redirect.
22     */

23    if (rt->u.dst.rate_tokens == 0 || time_after(jiffies, (rt->u.dst.rate_last (ip_rt_redirect_load << rt->u.dst.rate_tokens)))) {
24        icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
25        rt->u.dst.rate_last = jiffies;
26        ++rt->u.dst.rate_tokens;
27        
28    }

29}
   重定向差錯使用ip_rt_redirect_silence(默認為(HZ/50)<<10)、ip_rt_redirect_number(默認為9)和ip_rt_redirect_load(默認為HZ/50)3個量來控制發送的速率;rt->u.dst.rate_last記錄上次發送的時間,rt->u.dst.rate_tokens累計發送總數,最大值為ip_rt_redirect_number;當兩次發送的時間間隔超過ip_rt_redirect_silence或ip_rt_redirect_load<<rt->u.dst.rate_tokens,并且發送總數不超過ip_rt_redirect_number時,才允許發送一個,這樣一來,在ip_rt_redirect_silence間隔內,每次發送的超時呈2的指數增長,達到了變減速發送的效果,直到總數達到ip_rt_redirect_number時停止發送,這是因為源主機可能忽略了重定向消息所以停止發送;當ip_rt_redirect_silence時間過后,又允許發送了,這是因為認為源主機沒有更新路由所以又需要發送。
posted @ 2015-05-18 19:52 春秋十二月 閱讀(2812) | 評論 (0)編輯 收藏
     摘要:    接上篇初始化與創建,本篇闡述Socket操作和銷毀兩部分的實現。 Socket操作    系統調用read(v)、write(v)是用戶空間讀寫socket的一種方法,為了弄清楚它們是怎么通過VFS將請求轉發到特定協議的實現,下面以read為例(write同理),并假定文件描述符對應的是IPv4 TCP類型的socket...  閱讀全文
posted @ 2015-05-03 16:55 春秋十二月 閱讀(5301) | 評論 (0)編輯 收藏
     摘要: 引言    在Unix的世界里,萬物皆文件,通過虛擬文件系統VFS,程序可以用標準的Unix系統調用對不同的文件系統,甚至不同介質上的文件系統進行讀寫操作。對于網絡套接字socket也是如此,除了專屬的Berkeley Sockets API,還支持一些標準的文件IO系統調用如read(v)、write(v)和close等。那么為什么socket也支持文件IO系統調...  閱讀全文
posted @ 2015-05-03 16:31 春秋十二月 閱讀(8709) | 評論 (0)編輯 收藏
     摘要: 字符集合     依據RFC3986 2規范,HTTP URI中允許出現的US-ASCII字符的子集,可以分成保留、未保留及轉義這幾類,每類的全部字符列表如下       ● 保留:  : / ? # [ ] @ ! $ & '( ) * + ,; =共18個,一般...  閱讀全文
posted @ 2015-02-10 18:40 春秋十二月 閱讀(4759) | 評論 (1)編輯 收藏
     摘要: 腳本概述   nginx是一款著名的開源web服務器,為方便升級與恢復,編寫了一個簡單的腳本,因為升級備份了可執行文件和配置文件(后綴名為old),所以可用于恢復。當升級時,若nginx正在運行,則不中斷服務進行平滑升級,否則直接拷貝覆蓋;當恢復時,若nginx正在運行,則不中斷服務進行平滑恢復,否則直接拷貝覆蓋。是否正在運行根據pid來判斷,而pid從pid文件讀取...  閱讀全文
posted @ 2015-01-19 00:36 春秋十二月 閱讀(2060) | 評論 (0)編輯 收藏
     摘要:    本文描述了一種簡單的跨平臺鎖框架的設計與實現,該框架小巧實用、易于擴展,它的特點如下:      ● 實現了線程間互斥鎖      ● 實現優化了單線程環境中的空鎖和空級別鎖      ● 支持編譯時或運行時選擇鎖   ...  閱讀全文
posted @ 2014-12-28 23:38 春秋十二月 閱讀(2474) | 評論 (6)編輯 收藏
   眾所周知,TLS是指線程局部存儲,FIFO是Unix中的命名管道,可用于無關進程間的通信,而本文描述的TLS FIFO是指這樣一種機制:如果一個線程在每次IO操作時,若沒有連接,則先連接到FIFO服務端,再將連接關聯到這個線程的TLS中,這里的連接即創建并打開唯一的FIFO,之后的讀寫就在這個FIFO連接上進行;當FIFO連接斷開時,在下次IO操作時會自動重連。這樣一來,用戶程序就只要調用相關的IO操作,而不必管理連接,極大地簡化了程序。使用FIFO通信前先要創建FIFO再打開它,其中創建是最重要的操作,結果有3種情況:成功、失敗和已存在。

結構定義
typedef struct 
{
    int fd;
    char *name;
}ipc_fifo_t;
  fd存儲FIFO文件描述符,name存儲FIFO文件系統路徑名。

接口函數
   創建FIFO
ipc_fifo_t* ipc_fifo_make(const char *path,mode_t mode);
  path指定FIFO路徑,可以是絕對路徑或相對路徑,mode指定訪問權限,若成功則返回一個FIFO結構,否則為NULL;通常被ipc_fifo_open調用。
   
   打開FIFO
int ipc_fifo_open(ipc_fifo_t **f,const char *path,int flag,mode_t mode);
  flag指定打開標志,如果包含了O_CREAT標志,那么調用ipc_fifo_make創建新的FIFO對象并在打開成功后替換*f,否則如果*f為空,就分配并初始化一個fifo結構;mode指定訪問權限,僅當創建時生效。雖然f為輸入輸出參數,但操作失敗時不會影響它,也就是說沒有副作用。

  ● 發送數據   
ssize_t ipc_fifo_write(ipc_fifo_t *f,const void *data,size_t size);
  如果成功則返回已發送的字節數,否則返回-1,errno表示出錯代碼。
   
  ● 接收數據
ssize_t ipc_fifo_read(ipc_fifo_t *f,void *data,size_t size);
  如果成功則返回已發送的字節數,否則返回-1,errno表示出錯代碼。

  ● 關閉FIFO
void ipc_fifo_close(ipc_fifo_t *f);
  當通信結束的時候,應該調用此函數來關閉FIFO,它會先刪除FIFO文件和關閉文件描述符,最后釋放fifo結構。

  ● 獲取TLS FIFO
ipc_fifo_t* ipc_fifo_tls_get();
  該函數一般被發送數據接口調用,若成功則返回一個FIFO結構,否則為NULL;每個線程對應一個FIFO對象,對于同一線程,獲取的是同一個FIFO對象,而后便可調用ipc_fifo_write來發送數據。

工作流程
  創建FIFO
  適用于FIFO客戶端和服務端,但服務端由于要異步處理眾多FIFO客戶端,因此要注意以下2個問題,這也是使用FIFO技術通信的一些細節。
  1)必須以非阻塞讀寫方式打開知名FIFO,即以O_CREAT|O_RDWR|O_NONBLOCK標志來調用ipc_fifo_open,這樣才不會阻塞等待某個客戶端以同步寫方式打開知名FIFO而返回,因為它使用O_RDWR標志,這樣自己既讀又寫,加上O_NONBLOCK,就立即返回了。
  2)必須以非阻塞只讀方式打開對應客戶端FIFO,即以O_RDONLY|O_NONBLOCK標志調用ipc_fifo_open,這樣就不會阻塞接受客戶端建立連接而返回。

  建立FIFO連接
  適用于FIFO客戶端,被發送數據接口調用,考慮到服務端可能事先沒有打開知名FIFO來監聽連接,所以這里先以異步方式寫打開知名FIFO,如果成功則改以阻塞方式發送唯一路徑名到服務端,如果發送完全后,接著以同步方式寫打開唯一FIFO,這是為了等待服務端打開了對應的唯一FIFO。

  發送數據

  適用于FIFO客戶端,當TLS中沒有關聯對應的FIFO時,則先調用fifo_tls_get進入建立FIFO連接流程,而后再發數據。
posted @ 2014-12-01 00:13 春秋十二月 閱讀(1365) | 評論 (2)編輯 收藏
     摘要:    Web服務器為了支持https訪問,通常會使用第三方庫openssl實現,而且為了高性能采用異步事件驅動模型,因此連接套接字被設為非阻塞類型,本文在nginx ssl模塊的基礎上,簡化提取它的核心框架,使用面向對象的方式描述,從握手、讀寫和關閉3個方面進行了分析,由于這3個操作都是異步的,因此操作失敗后要調用SSL_get_error來獲取錯誤碼,有如下4種情況。 &n...  閱讀全文
posted @ 2014-04-11 17:26 春秋十二月 閱讀(14042) | 評論 (0)編輯 收藏
僅列出標題
共17頁: First 6 7 8 9 10 11 12 13 14 Last 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美寡妇偷汉性猛交| 噜噜噜躁狠狠躁狠狠精品视频| 日韩视频永久免费| 亚洲四色影视在线观看| 国产精品视频一二| 欧美成人69av| 午夜精品一区二区三区电影天堂| 每日更新成人在线视频| 久久亚洲不卡| 国产精品99久久久久久久女警| 亚洲二区精品| 国产精品久久久久久久久免费樱桃| 亚洲在线视频观看| 亚洲黄一区二区三区| 国产精品久久久久高潮| 久久嫩草精品久久久久| 午夜日韩av| 免费成年人欧美视频| 欧美一区高清| 欧美亚洲自偷自偷| 老司机一区二区| 久久久久五月天| 久久国产欧美| 久久精品2019中文字幕| 欧美理论电影网| 欧美精品91| 欧美日本国产在线| 国产一区二区三区奇米久涩| 国产欧美二区| 国产乱码精品一区二区三区不卡 | 在线视频亚洲欧美| 日韩亚洲欧美精品| 一区二区三区欧美激情| 久久久亚洲国产天美传媒修理工| 欧美一区二区三区四区在线观看地址| 亚洲视频视频在线| 久久久久久久999| 久久久久久夜| 一二三四社区欧美黄| 亚洲视频在线观看| 亚洲欧美国产毛片在线| 亚洲伊人观看| 欧美精品尤物在线| 国内外成人在线视频| 国产精品v欧美精品∨日韩| 欧美精品一区二区三区久久久竹菊| 国产欧美韩日| 西西人体一区二区| 久久综合色婷婷| 亚洲免费在线电影| 国产精品国产精品| 一区二区久久久久久| 亚洲电影av| 一本色道久久综合亚洲二区三区 | 久久岛国电影| 国产美女一区| 久久精品女人的天堂av| 久久婷婷一区| 欧美在线短视频| 欧美www视频在线观看| 激情国产一区二区| 麻豆精品在线观看| 亚洲影视在线| 欧美视频在线观看视频极品| 国产精品日本精品| 国产精品99久久久久久www| 亚洲第一福利社区| 欧美freesex交免费视频| 国产精品v欧美精品v日本精品动漫| 91久久夜色精品国产九色| 一区二区三区视频观看| 亚洲国产1区| 欧美日韩国产综合新一区| 国产裸体写真av一区二区| 午夜欧美不卡精品aaaaa| 免费在线成人av| 亚洲视频一区二区免费在线观看| 亚洲欧美国内爽妇网| 国产欧美日韩免费| 久久五月天婷婷| 女女同性女同一区二区三区91| 亚洲国内在线| 麻豆成人精品| 欧美美女操人视频| 亚洲欧美国产77777| 欧美成人亚洲成人日韩成人| 欧美va天堂va视频va在线| 正在播放亚洲| 欧美伊人久久大香线蕉综合69| 亚洲国产你懂的| 亚洲午夜免费视频| 一区二区在线观看av| 日韩视频中文字幕| 国内欧美视频一区二区| 亚洲人体偷拍| 欧美精选午夜久久久乱码6080| 一区二区三区**美女毛片| 午夜性色一区二区三区免费视频 | 欧美系列精品| 久久嫩草精品久久久精品| 欧美精品三级日韩久久| 欧美在线一二三区| 亚洲无线视频| 在线精品国产成人综合| 久久看片网站| 欧美岛国激情| 久久久久国产一区二区三区四区| 欧美激情综合网| 久久亚洲欧洲| 国产精品亚洲欧美| 亚洲国产影院| 欧美日韩大片一区二区三区| 欧美专区在线观看| 欧美日韩在线精品一区二区三区| 亚洲美女精品成人在线视频| 欧美大香线蕉线伊人久久国产精品| 欧美精品一区二区三区久久久竹菊| 久久久之久亚州精品露出| 国产精品麻豆欧美日韩ww| 亚洲精品国久久99热| 1024成人网色www| 红桃视频一区| 亚洲激情在线观看| 在线免费不卡视频| 午夜日本精品| 欧美呦呦网站| 国产精品区一区二区三区| 亚洲精品视频在线播放| 欧美日韩国产一区| 欧美激情欧美激情在线五月| 欧美精品一区二区视频 | 亚洲一区二区三区成人在线视频精品| 亚洲人被黑人高潮完整版| 久久久久一区| 美国三级日本三级久久99| 国产一区二区三区在线观看网站 | 黄色一区二区三区四区| 欧美一级二区| 久久久久高清| 激情五月***国产精品| 久久精品一本久久99精品| 9l视频自拍蝌蚪9l视频成人| 一区二区三区精品久久久| 99视频一区二区三区| 欧美成人69| 99精品欧美一区二区三区| 狠狠久久五月精品中文字幕| 午夜天堂精品久久久久 | 亚洲一区二区三区视频播放| 亚洲欧美日韩天堂| 国产乱肥老妇国产一区二 | 亚洲黄网站黄| 欧美激情欧美激情在线五月| 亚洲精品久久久一区二区三区| 99这里有精品| 国产精品综合不卡av| 久久久久久9| 亚洲美女黄网| 欧美一级久久久| 尤物yw午夜国产精品视频明星| 在线中文字幕不卡| 欧美一区在线看| 亚洲高清一区二| 欧美视频导航| 久久久91精品国产一区二区三区 | 久久精品国产久精国产爱| 欧美大片免费观看| 亚洲一区二区三区久久| 欧美va天堂va视频va在线| 亚洲欧洲视频| 久久久久国产精品麻豆ai换脸| 亚洲精品视频在线| 欧美+日本+国产+在线a∨观看| 亚洲啪啪91| 久久精品水蜜桃av综合天堂| 亚洲精品美女免费| 国产视频一区免费看| 亚洲欧美在线看| 亚洲一区二区毛片| 国产在线不卡| 欧美日韩国产一中文字不卡| 国产精品三级久久久久久电影| 亚洲综合视频一区| 欧美激情按摩在线| 欧美一级网站| 亚洲精品日韩在线| 国产美女精品视频| 欧美另类69精品久久久久9999| 欧美在线播放一区| 亚洲一级二级在线| 亚洲精品午夜| 欧美电影免费网站| 久久色在线播放| 亚洲免费视频在线观看| 91久久综合亚洲鲁鲁五月天| 国内精品美女在线观看| 国产精品久久久久影院亚瑟| 欧美激情1区| 一区二区三区你懂的| 亚洲级视频在线观看免费1级|