> 데이터 베이스 > MySQL 튜토리얼 > memcached探索之thread model(2)

memcached探索之thread model(2)

WBOY
풀어 주다: 2016-06-07 15:11:26
원래의
1168명이 탐색했습니다.

6. 下面我们看看主线程dispatch_thread的事件处理设置。在memcached.c中的main函数中 /* create unix mode sockets after dropping privileges */ if ( settings . socketpath ! = NULL ) { errno = 0 ; if ( server_socket_unix ( settings . socketpath ,

6. 下面我们看看主线程dispatch_thread的事件处理设置。在memcached.c中的main函数中

<span><font face="新宋体"><span>/* create unix mode sockets after dropping privileges */</span><br>    <span>if</span> <span>(</span>settings<span>.</span>socketpath <span>!</span><span>=</span> <span>NULL</span><span>)</span> <span>{</span><br>        <span>errno</span> <span>=</span> 0<span>;</span><br>        <span>if</span> <span>(</span>server_socket_unix<span>(</span>settings<span>.</span>socketpath<span>,</span>settings<span>.</span>access<span>)</span><span>)</span> <span>{</span><br>            vperror<span>(</span><span>"failed to listen on UNIX socket: %s"</span><span>,</span> settings<span>.</span>socketpath<span>)</span><span>;</span><br>            <span>exit</span><span>(</span>EX_OSERR<span>)</span><span>;</span><br>        <span>}</span><br>    <span>}</span><br><br>    <span>/* create the listening socket, bind it, and init */</span><br>    <span>if</span> <span>(</span>settings<span>.</span>socketpath <span>=</span><span>=</span> <span>NULL</span><span>)</span> <span>{</span><br>        <span>int</span> udp_port<span>;</span><br><br>        <span>const</span> <span>char</span> <span>*</span>portnumber_filename <span>=</span> <span>getenv</span><span>(</span><span>"MEMCACHED_PORT_FILENAME"</span><span>)</span><span>;</span><br>        <span>char</span> temp_portnumber_filename<span>[</span>PATH_MAX<span>]</span><span>;</span><br>        <span>FILE</span> <span>*</span>portnumber_file <span>=</span> <span>NULL</span><span>;</span><br><br>        <span>if</span> <span>(</span>portnumber_filename <span>!</span><span>=</span> <span>NULL</span><span>)</span> <span>{</span><br>            snprintf<span>(</span>temp_portnumber_filename<span>,</span><br>                     <span>sizeof</span><span>(</span>temp_portnumber_filename<span>)</span><span>,</span><br>                     <span>"%s.lck"</span><span>,</span> portnumber_filename<span>)</span><span>;</span><br><br>            portnumber_file <span>=</span> <span>fopen</span><span>(</span>temp_portnumber_filename<span>,</span> <span>"a"</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span>portnumber_file <span>=</span><span>=</span> <span>NULL</span><span>)</span> <span>{</span><br>                <span>fprintf</span><span>(</span><span>stderr</span><span>,</span> <span>"Failed to open \"%s\": %s\n"</span><span>,</span><br>                        temp_portnumber_filename<span>,</span> <span>strerror</span><span>(</span><span>errno</span><span>)</span><span>)</span><span>;</span><br>            <span>}</span><br>        <span>}</span><br><br>        <span>errno</span> <span>=</span> 0<span>;</span><br>        <span>if</span> <span>(</span>settings<span>.</span>port <span>&</span><span>&</span> server_socket<span>(</span>settings<span>.</span>port<span>,</span> tcp_transport<span>,</span><br>                                           portnumber_file<span>)</span><span>)</span> <span>{</span><br>            vperror<span>(</span><span>"failed to listen on TCP port %d"</span><span>,</span> settings<span>.</span>port<span>)</span><span>;</span><br>            <span>exit</span><span>(</span>EX_OSERR<span>)</span><span>;</span><br>        <span>}</span><br><br>        </font><font face="新宋体"><span>/*<br>         * initialization order: first create the listening sockets<br>         * (may need root on low ports), then drop root if needed,<br>         * then daemonise if needed, then init libevent (in some cases<br>         * descriptors created by libevent wouldn't survive forking).<br>         */</span><br>        udp_port <span>=</span> settings<span>.</span>udpport <span>?</span> settings<span>.</span>udpport <span>:</span> settings<span>.</span>port<span>;</span><br><br>        <span>/* create the UDP listening socket and bind it */</span><br>        <span>errno</span> <span>=</span> 0<span>;</span><br>        <span>if</span> <span>(</span>settings<span>.</span>udpport <span>&</span><span>&</span> server_socket<span>(</span>settings<span>.</span>udpport<span>,</span> udp_transport<span>,</span><br>                                              portnumber_file<span>)</span><span>)</span> <span>{</span><br>            vperror<span>(</span><span>"failed to listen on UDP port %d"</span><span>,</span> settings<span>.</span>udpport<span>)</span><span>;</span><br>            <span>exit</span><span>(</span>EX_OSERR<span>)</span><span>;</span><br>        <span>}</span><br><br>        <span>if</span> <span>(</span>portnumber_file<span>)</span> <span>{</span><br>            <span>fclose</span><span>(</span>portnumber_file<span>)</span><span>;</span><br>            <span>rename</span><span>(</span>temp_portnumber_filename<span>,</span> portnumber_filename<span>)</span><span>;</span><br>        <span>}</span><br>    <span>}</span><br>    <span>/* Drop privileges no longer needed */</span><br>    drop_privileges<span>(</span><span>)</span><span>;</span><br>    <span>/* enter the event loop */</span><br>    event_base_loop<span>(</span>main_base<span>,</span> 0<span>)</span><span>; //主线程(dispatcher_thread)的事件监听循环。。。</span></font></span>

<span><font face="新宋体"><span></span><br></font></span>


7. 继续跟踪server_socket函数(memcached.c中)

<span><font face="新宋体"><span>/**<br> * Create a socket and bind it to a specific port number<br> * @param port the port number to bind to<br> * @param transport the transport protocol (TCP / UDP)<br> * @param portnumber_file A filepointer to write the port numbers to<br> * when they are successfully added to the list of ports we<br> * listen on.<br> */</span><br><span>static</span> <span>int</span> server_socket<span>(</span><span>int</span> port<span>,</span> <span>enum</span> network_transport transport<span>,</span><br>                         <span>FILE</span> <span>*</span>portnumber_file<span>)</span> <span>{</span><br>    <span>int</span> sfd<span>;</span><br>    <span>struct</span> <span>linger</span> ling <span>=</span> <span>{</span>0<span>,</span> 0<span>}</span><span>;</span><br>    <span>struct</span> <span>addrinfo</span> <span>*</span>ai<span>;</span><br>    <span>struct</span> <span>addrinfo</span> <span>*</span>next<span>;</span><br>    <span>struct</span> <span>addrinfo</span> hints <span>=</span> <span>{</span> <span>.</span>ai_flags <span>=</span> <span>AI_PASSIVE</span><span>,</span><br>                              <span>.</span>ai_family <span>=</span> <span>AF_UNSPEC</span> <span>}</span><span>;</span><br>    <span>char</span> port_buf<span>[</span><span>NI_MAXSERV</span><span>]</span><span>;</span><br>    <span>int</span> <span>error</span><span>;</span><br>    <span>int</span> success <span>=</span> 0<span>;</span><br>    <span>int</span> flags <span>=</span>1<span>;</span><br><br>    hints<span>.</span>ai_socktype <span>=</span> IS_UDP<span>(</span>transport<span>)</span> <span>?</span> <span>SOCK_DGRAM</span> <span>:</span> <span>SOCK_STREAM</span><span>;</span><br><br>    <span>if</span> <span>(</span>port <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>        port <span>=</span> 0<span>;</span><br>    <span>}</span><br>    snprintf<span>(</span>port_buf<span>,</span> <span>sizeof</span><span>(</span>port_buf<span>)</span><span>,</span> <span>"%d"</span><span>,</span> port<span>)</span><span>;</span><br>    <span>error</span><span>=</span> <span>getaddrinfo</span><span>(</span>settings<span>.</span>inter<span>,</span> port_buf<span>,</span> <span>&</span>hints<span>,</span> <span>&</span>ai<span>)</span><span>;</span><br>    <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span> <span>{</span><br>        <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> <span>EAI_SYSTEM</span><span>)</span><br>          <span>fprintf</span><span>(</span><span>stderr</span><span>,</span> <span>"getaddrinfo(): %s\n"</span><span>,</span> <span>gai_strerror</span><span>(</span><span>error</span><span>)</span><span>)</span><span>;</span><br>        <span>else</span><br>          <span>perror</span><span>(</span><span>"getaddrinfo()"</span><span>)</span><span>;</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br><br>    <span>for</span> <span>(</span>next<span>=</span> ai<span>;</span> next<span>;</span> next<span>=</span> next<span>-</span><span>></span>ai_next<span>)</span> <span>{</span><br>        conn <span>*</span>listen_conn_add<span>;</span><br>        <span>if</span> <span>(</span><span>(</span>sfd <span>=</span> new_socket<span>(</span>next<span>)</span><span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{ <span>//creat socket</span></span><br>            </font><font face="新宋体"><span>/* getaddrinfo can return "junk" addresses,<br>             * we make sure at least one works before erroring.<br>             */</span><br>            <span>continue</span><span>;</span><br>        <span>}</span><br><br><span>#</span><span>ifdef</span> IPV6_V6ONLY<br>        <span>if</span> <span>(</span>next<span>-</span><span>></span>ai_family <span>=</span><span>=</span> <span>AF_INET6</span><span>)</span> <span>{</span><br>            <span>error</span> <span>=</span> <span>setsockopt</span><span>(</span>sfd<span>,</span> <span>IPPROTO_IPV6</span><span>,</span> IPV6_V6ONLY<span>,</span> <span>(</span><span>char</span> <span>*</span><span>)</span> <span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span> <span>{</span><br>                <span>perror</span><span>(</span><span>"setsockopt"</span><span>)</span><span>;</span><br>                <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>                <span>continue</span><span>;</span><br>            <span>}</span><br>        <span>}</span><br><span>#</span><span>endif</span><br>  <span>      </span></font></span>//setsockopt
<span><font face="新宋体">        <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_REUSEADDR<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>; </span><br>        <span>if</span> <span>(</span>IS_UDP<span>(</span>transport<span>)</span><span>)</span> <span>{</span><br>            maximize_sndbuf<span>(</span>sfd<span>)</span><span>;</span><br>        <span>}</span> <span>else</span> <span>{</span><br>            <span>error</span> <span>=</span> <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_KEEPALIVE<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span><br>                <span>perror</span><span>(</span><span>"setsockopt"</span><span>)</span><span>;</span><br><br>            <span>error</span> <span>=</span> <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_LINGER<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>ling<span>,</span> <span>sizeof</span><span>(</span>ling<span>)</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span><br>                <span>perror</span><span>(</span><span>"setsockopt"</span><span>)</span><span>;</span><br><br>            <span>error</span> <span>=</span> <span>setsockopt</span><span>(</span>sfd<span>,</span> <span>IPPROTO_TCP</span><span>,</span> TCP_NODELAY<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>            <span>if</span> <span>(</span><span>error</span> <span>!</span><span>=</span> 0<span>)</span><br>                <span>perror</span><span>(</span><span>"setsockopt"</span><span>)</span><span>;</span><br>        <span>}</span><br>  <span>      //bind</span><br>        <span>if</span> <span>(</span><span>bind</span><span>(</span>sfd<span>,</span> next<span>-</span><span>></span>ai_addr<span>,</span> next<span>-</span><span>></span>ai_addrlen<span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>            <span>if</span> <span>(</span><span>errno</span> <span>!</span><span>=</span> EADDRINUSE<span>)</span> <span>{</span><br>                <span>perror</span><span>(</span><span>"bind()"</span><span>)</span><span>;</span><br>                <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>                <span>freeaddrinfo</span><span>(</span>ai<span>)</span><span>;</span><br>                <span>return</span> 1<span>;</span><br>            <span>}</span><br>            <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>            <span>continue</span><span>;</span><br>        <span>}</span> <span>else</span> <span>{</span><br>            success<span>+</span><span>+</span><span>;</span></font></span>

<span><span></span><font face="新宋体">         <span>   //TCP listen</span><br>            <span>if</span> <span>(</span><span>!</span>IS_UDP<span>(</span>transport<span>)</span> <span>&</span><span>&</span> <span>listen</span><span>(</span>sfd<span>,</span> settings<span>.</span>backlog<span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>                <span>perror</span><span>(</span><span>"listen()"</span><span>)</span><span>;</span><br>                <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>                <span>freeaddrinfo</span><span>(</span>ai<span>)</span><span>;</span><br>                <span>return</span> 1<span>;</span><br>            <span>}</span><br>            <span>if</span> <span>(</span>portnumber_file <span>!</span><span>=</span> <span>NULL</span> <span>&</span><span>&</span><br>                <span>(</span>next<span>-</span><span>></span>ai_addr<span>-</span><span>></span>sa_family <span>=</span><span>=</span> <span>AF_INET</span> <span>|</span><span>|</span><br>                 next<span>-</span><span>></span>ai_addr<span>-</span><span>></span>sa_family <span>=</span><span>=</span> <span>AF_INET6</span><span>)</span><span>)</span> <span>{</span><br>                <span>union</span> <span>{</span><br>                    <span>struct</span> <span>sockaddr_in</span> in<span>;</span><br>                    <span>struct</span> <span>sockaddr_in6</span> in6<span>;</span><br>                <span>}</span> my_sockaddr<span>;</span><br>                <span>socklen_t</span> len <span>=</span> <span>sizeof</span><span>(</span>my_sockaddr<span>)</span><span>;</span><br>                <span>if</span> <span>(</span><span>getsockname</span><span>(</span>sfd<span>,</span> <span>(</span><span>struct</span> <span>sockaddr</span><span>*</span><span>)</span><span>&</span>my_sockaddr<span>,</span> <span>&</span>len<span>)</span><span>=</span><span>=</span>0<span>)</span> <span>{</span><br>                    <span>if</span> <span>(</span>next<span>-</span><span>></span>ai_addr<span>-</span><span>></span>sa_family <span>=</span><span>=</span> <span>AF_INET</span><span>)</span> <span>{</span><br>                        <span>fprintf</span><span>(</span>portnumber_file<span>,</span> <span>"%s INET: %u\n"</span><span>,</span><br>                                IS_UDP<span>(</span>transport<span>)</span> <span>?</span> <span>"UDP"</span> <span>:</span> <span>"TCP"</span><span>,</span><br>                                <span>ntohs</span><span>(</span>my_sockaddr<span>.</span>in<span>.</span>sin_port<span>)</span><span>)</span><span>;</span><br>                    <span>}</span> <span>else</span> <span>{</span><br>                        <span>fprintf</span><span>(</span>portnumber_file<span>,</span> <span>"%s INET6: %u\n"</span><span>,</span><br>                                IS_UDP<span>(</span>transport<span>)</span> <span>?</span> <span>"UDP"</span> <span>:</span> <span>"TCP"</span><span>,</span><br>                                <span>ntohs</span><span>(</span>my_sockaddr<span>.</span>in6<span>.</span>sin6_port<span>)</span><span>)</span><span>;</span><br>                    <span>}</span><br>                <span>}</span><br>            <span>}</span><br>        <span>}</span><br><br>        <span>if</span> <span>(</span>IS_UDP<span>(</span>transport<span>)</span><span>)</span> </font><span><font face="新宋体">{ <br></font></span></span>

<font face="新宋体">            //UDP 的处理中不需要accept,所以直接派发connection到工作线程。</font><span><span></span><br><font face="新宋体">            <span>int</span> c<span>;</span><br><br>            <span>for</span> <span>(</span>c <span>=</span> 0<span>;</span> c <span> settings<span>.</span>num_threads<span>;</span> c<span>+</span><span>+</span><span>)</span> <span>{</span><br>                <span>/* this is guaranteed to hit all threads because we round-robin */</span><br>                dispatch_conn_new<span>(</span>sfd<span>,</span> conn_read<span>,</span> EV_READ <span>|</span> EV_PERSIST<span>,</span><br>                                  UDP_READ_BUFFER_SIZE<span>,</span> transport<span>)</span><span>;</span><br>            <span>}</span><br>        <span>}</span> <span>else</span> </span></font><span><font face="新宋体">{  <br></font></span></span>

<span><span><font face="新宋体">         <span> <span> //TCP的处理(注意,这里dispatcher_thread同样调用了conn_new来绑定conn_event到其main_base. 并且此时conn的初始状态为conn_listening, 事件为持久可读, 而在conn_new中注册了conn_event的回调函数为event_handler,所以,dispatche_thread在当前listen的socket可读时就会调用event_handler,进而调用driver_machine(c) 进入状态机。而在driver_machine中如果是主线程(dispatcher_thread)则会在accept socket后调用dispatch_new_conn函数来给各worker_thread派发connection...)</span></span></font></span></span><span><span></span><br><font face="新宋体">            <span>if</span> <span>(</span><span>!</span><span>(</span>listen_conn_add <span>=</span> conn_new<span>(</span>sfd<span>,</span> conn_listening<span>,</span><br>                                             EV_READ <span>|</span> EV_PERSIST<span>,</span> 1<span>,</span><br>                                             transport<span>,</span> main_base<span>)</span><span>)</span><span>)</span> <span>{</span><br>                <span>fprintf</span><span>(</span><span>stderr</span><span>,</span> <span>"failed to create listening connection\n"</span><span>)</span><span>;</span><br>                <span>exit</span><span>(</span><span>EXIT_FAILURE</span><span>)</span><span>;</span><br>            <span>}</span><br>            listen_conn_add<span>-</span><span>></span>next <span>=</span> listen_conn<span>;</span><br>            listen_conn <span>=</span> listen_conn_add<span>;</span><br>        <span>}</span><br>    <span>}</span><br><br>    <span>freeaddrinfo</span><span>(</span>ai<span>)</span><span>;</span><br><br>    <span>/* Return zero iff we detected no errors in starting up connections */</span><br>    <span>return</span> success <span>=</span><span>=</span> 0<span>;</span><br><span>}</span></font></span>


8. 看看UDP和TCP模式下dispatcher_thread都会调用的dispatch_new_conn函数(在thread.c中)

<span><font face="新宋体"><span>/*<br> * Dispatches a new connection to another thread. This is only ever called<br> * from the main thread, either during initialization (for UDP) or because<br> * of an incoming connection.<br> */</span><br><span>void</span> dispatch_conn_new<span>(</span><span>int</span> sfd<span>,</span> <span>enum</span> conn_states init_state<span>,</span> <span>int</span> event_flags<span>,</span><br>                       <span>int</span> read_buffer_size<span>,</span> <span>enum</span> network_transport transport<span>)</span> <span>{</span><br>    CQ_ITEM <span>*</span>item <span>=</span> cqi_new<span>(</span><span>)</span><span>;</span><br>    <span>int</span> tid <span>=</span> <span>(</span>last_thread <span>+</span> 1<span>)</span> <span>%</span> settings<span>.</span>num_threads<span>; //轮询的方式找worker_thread</span><br><br>    LIBEVENT_THREAD <span>*</span>thread <span>=</span> threads <span>+</span> tid<span>;</span><br><br>    last_thread <span>=</span> tid<span>;</span><br><br>    item<span>-</span><span>></span>sfd <span>=</span> sfd<span>;</span><br>    item<span>-</span><span>></span>init_state <span>=</span> init_state<span>;</span><br>    item<span>-</span><span>></span>event_flags <span>=</span> event_flags<span>;</span><br>    item<span>-</span><span>></span>read_buffer_size <span>=</span> read_buffer_size<span>;</span><br>    item<span>-</span><span>></span>transport <span>=</span> transport<span>;</span><br>  </font><span>  </span></span><span><span>//push conn到worker_thread的CQ中</span></span>
<span><font face="新宋体">    cq_push<span>(</span>thread<span>-</span><span>></span>new_conn_queue<span>,</span> item<span>)</span><span>; </span><br><br>    MEMCACHED_CONN_DISPATCH<span>(</span>sfd<span>,</span> thread<span>-</span><span>></span>thread_id<span>)</span><span>;</span><br>    <span>if</span> <span>(</span><span>write</span><span>(</span>thread<span>-</span><span>></span>notify_send_fd<span>,</span> <span>""</span><span>,</span> 1<span>)</span> <span>!</span><span>=</span> 1<span>)</span> <span>{</span><br>        <span>perror</span><span>(</span><span>"Writing to thread notify pipe"</span><span>)</span><span>;</span><br>    <span>}</span><br><span>}</span><br></font></span>


9. 先看看unix domain socket模式下主线程的事件处理设置。(在上面的6中调用的 server_socket_unix函数

<span><font face="新宋体"><span>static</span> <span>int</span> server_socket_unix<span>(</span><span>const</span> <span>char</span> <span>*</span>path<span>,</span> <span>int</span> access_mask<span>)</span> <span>{</span><br>    <span>int</span> sfd<span>;</span><br>    <span>struct</span> <span>linger</span> ling <span>=</span> <span>{</span>0<span>,</span> 0<span>}</span><span>;</span><br>    <span>struct</span> <span>sockaddr_un</span> addr<span>;</span><br>    <span>struct</span> stat tstat<span>;</span><br>    <span>int</span> flags <span>=</span>1<span>;</span><br>    <span>int</span> old_umask<span>;</span><br><br>    <span>if</span> <span>(</span><span>!</span>path<span>)</span> <span>{</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br><br>    <span>if</span> <span>(</span><span>(</span>sfd <span>=</span> new_socket_unix<span>(</span><span>)</span><span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br><br>    </font><font face="新宋体"><span>/*<br>     * Clean up a previous socket file if we left it around<br>     */</span><br>    <span>if</span> <span>(</span>lstat<span>(</span>path<span>,</span> <span>&</span>tstat<span>)</span> <span>=</span><span>=</span> 0<span>)</span> <span>{</span><br>        <span>if</span> <span>(</span>S_ISSOCK<span>(</span>tstat<span>.</span>st_mode<span>)</span><span>)</span><br>            unlink<span>(</span>path<span>)</span><span>;</span><br>    <span>}</span><br><br>    <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_REUSEADDR<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>    <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_KEEPALIVE<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>flags<span>,</span> <span>sizeof</span><span>(</span>flags<span>)</span><span>)</span><span>;</span><br>    <span>setsockopt</span><span>(</span>sfd<span>,</span> SOL_SOCKET<span>,</span> SO_LINGER<span>,</span> <span>(</span><span>void</span> <span>*</span><span>)</span><span>&</span>ling<span>,</span> <span>sizeof</span><span>(</span>ling<span>)</span><span>)</span><span>;</span><br><br>    </font><font face="新宋体"><span>/*<br>     * the memset call clears nonstandard fields in some impementations<br>     * that otherwise mess things up.<br>     */</span><br>    <span>memset</span><span>(</span><span>&</span>addr<span>,</span> 0<span>,</span> <span>sizeof</span><span>(</span>addr<span>)</span><span>)</span><span>;</span><br><br>    addr<span>.</span>sun_family <span>=</span> <span>AF_UNIX</span><span>;</span><br>    <span>strncpy</span><span>(</span>addr<span>.</span>sun_path<span>,</span> path<span>,</span> <span>sizeof</span><span>(</span>addr<span>.</span>sun_path<span>)</span> <span>-</span> 1<span>)</span><span>;</span><br>    <span>assert</span><span>(</span><span>strcmp</span><span>(</span>addr<span>.</span>sun_path<span>,</span> path<span>)</span> <span>=</span><span>=</span> 0<span>)</span><span>;</span><br>    old_umask <span>=</span> umask<span>(</span> <span>~</span><span>(</span>access_mask<span>&</span>0777<span>)</span><span>)</span><span>;</span><br>    <span>if</span> <span>(</span><span>bind</span><span>(</span>sfd<span>,</span> <span>(</span><span>struct</span> <span>sockaddr</span> <span>*</span><span>)</span><span>&</span>addr<span>,</span> <span>sizeof</span><span>(</span>addr<span>)</span><span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>        <span>perror</span><span>(</span><span>"bind()"</span><span>)</span><span>;</span><br>        <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>        umask<span>(</span>old_umask<span>)</span><span>;</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br>    umask<span>(</span>old_umask<span>)</span><span>;</span><br>    <span>if</span> <span>(</span><span>listen</span><span>(</span>sfd<span>,</span> settings<span>.</span>backlog<span>)</span> <span>=</span><span>=</span> <span>-</span>1<span>)</span> <span>{</span><br>        <span>perror</span><span>(</span><span>"listen()"</span><span>)</span><span>;</span><br>        <span>close</span><span>(</span>sfd<span>)</span><span>;</span><br>        <span>return</span> 1<span>;</span><br>    <span>}</span><br>    <span>if</span> <span>(</span><span>!</span><span>(</span>listen_conn <span>=</span> conn_new<span>(</span>sfd<span>,</span> conn_listening<span>, //同样是调用conn_new</span><br>                                 EV_READ <span>|</span> EV_PERSIST<span>,</span> 1<span>,</span><br>                                 local_transport<span>,</span> main_base<span>)</span><span>)</span><span>)</span> <span>{</span><br>        <span>fprintf</span><span>(</span><span>stderr</span><span>,</span> <span>"failed to create listening connection\n"</span><span>)</span><span>;</span><br>        <span>exit</span><span>(</span><span>EXIT_FAILURE</span><span>)</span><span>;</span><br>    <span>}</span><br><br>    <span>return</span> 0<span>;</span><br><span>}</span></font><br></span>


원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿