Home > Database > Mysql Tutorial > memcached探索之thread model(2)

memcached探索之thread model(2)

WBOY
Release: 2016-06-07 15:11:26
Original
1168 people have browsed it

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>


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template