Heim > Datenbank > MySQL-Tutorial > MySQL 服务器监听客户端连接源码

MySQL 服务器监听客户端连接源码

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Freigeben: 2016-06-07 17:01:48
Original
948 Leute haben es durchsucht

在下面的代码有,有些结构体还不清楚,如THD,st_vio,pollfd等。但可以看出MySQL使用Select模型来接收客户端的连接。而且也在网上

在下面的代码有,有些结构体还不清楚,如THD,st_vio,pollfd等。但可以看出MySQL使用Select模型来接收客户端的连接。而且也在网上查清,unix_sock是指同一机器中不同进程间的通信,如命名管道。而ip_sock指的是不同主机间的通信。

void handle_connections_sockets()

{

  my_socket UNINIT_VAR(sock), UNINIT_VAR(new_sock);

  uint error_count=0;

  THD *thd;

  struct sockaddr_storage cAddr;

  int ip_flags=0,socket_flags=0,flags=0,retval;

  st_vio *vio_tmp;

#ifdef HAVE_POLL

  int socket_count= 0;

  struct pollfd fds[2]; // for ip_sock and unix_sock

#else

  fd_set readFDs,clientFDs;

  uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);

#endif

 

  DBUG_ENTER("handle_connections_sockets");

 

#ifndef HAVE_POLL

  FD_ZERO(&clientFDs);

#endif

 

  if (ip_sock != INVALID_SOCKET)

  {

#ifdef HAVE_POLL

    fds[socket_count].fd= ip_sock;

    fds[socket_count].events= POLLIN;

    socket_count++;

#else

    FD_SET(ip_sock,&clientFDs);

#endif   

#ifdef HAVE_FCNTL

    ip_flags = fcntl(ip_sock, F_GETFL, 0);

#endif

  }

#ifdef HAVE_SYS_UN_H

#ifdef HAVE_POLL

  fds[socket_count].fd= unix_sock;

  fds[socket_count].events= POLLIN;

  socket_count++;

#else

  FD_SET(unix_sock,&clientFDs);

#endif

#ifdef HAVE_FCNTL

  socket_flags=fcntl(unix_sock, F_GETFL, 0);

#endif

#endif

 

  DBUG_PRINT("general",("Waiting for connections."));

  MAYBE_BROKEN_SYSCALL;

  while (!abort_loop)

  {

#ifdef HAVE_POLL

    retval= poll(fds, socket_count, -1);

#else

    readFDs=clientFDs;

 

    retval= select((int) max_used_connection,&readFDs,0,0,0);//等待客户端连接,反回错误或有连接到来

#endif

 

    if (retval

    {

      if (socket_errno != SOCKET_EINTR)

      {

    if (!select_errors++ && !abort_loop)    /* purecov: inspected */

      sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */

      }

      MAYBE_BROKEN_SYSCALL

      continue;

    }

 

    if (abort_loop)

    {

      MAYBE_BROKEN_SYSCALL;

      break;

    }

 

    /* Is this a new connection request ? */

#ifdef HAVE_POLL

    for (int i= 0; i

    {

      if (fds[i].revents & POLLIN)//读取事件类型

      {

        sock= fds[i].fd;

#ifdef HAVE_FCNTL

        flags= fcntl(sock, F_GETFL, 0);

#else

        flags= 0;

#endif // HAVE_FCNTL

        break;

      }

    }

#else  // HAVE_POLL

#ifdef HAVE_SYS_UN_H

    if (FD_ISSET(unix_sock,&readFDs))

    {

      sock = unix_sock;

      flags= socket_flags;

    }

    else

#endif // HAVE_SYS_UN_H

    {

      sock = ip_sock;

      flags= ip_flags;

    }

#endif // HAVE_POLL

 

#if !defined(NO_FCNTL_NONBLOCK)

    if (!(test_flags & TEST_BLOCKING))

    {

#if defined(O_NONBLOCK)

      fcntl(sock, F_SETFL, flags | O_NONBLOCK);//设置为非阻塞模式

#elif defined(O_NDELAY)

      fcntl(sock, F_SETFL, flags | O_NDELAY);

#endif

    }

#endif /* NO_FCNTL_NONBLOCK */

    for (uint retry=0; retry

    {

      size_socket length= sizeof(struct sockaddr_storage);

      new_sock= accept(sock, (struct sockaddr *)(&cAddr),//接受连接,连接使用阻塞方式

                       &length);

      if (new_sock != INVALID_SOCKET ||

      (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))

    break;

      MAYBE_BROKEN_SYSCALL;

#if !defined(NO_FCNTL_NONBLOCK)

      if (!(test_flags & TEST_BLOCKING))

      {

    if (retry == MAX_ACCEPT_RETRY - 1)

      fcntl(sock, F_SETFL, flags);      // Try without O_NONBLOCK

      }

#endif

    }

#if !defined(NO_FCNTL_NONBLOCK)

    if (!(test_flags & TEST_BLOCKING))

      fcntl(sock, F_SETFL, flags);

#endif

    if (new_sock == INVALID_SOCKET)

    {

      if ((error_count++ & 255) == 0)        // This can happen often

    sql_perror("Error in accept");

      MAYBE_BROKEN_SYSCALL;

      if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)

    sleep(1);               // Give other threads some time

      continue;

    }

 

#ifdef HAVE_LIBWRAP

    {

      if (sock == ip_sock)

      {

    struct request_info req;

    signal(SIGCHLD, SIG_DFL);

    request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL);

    my_fromhost(&req);

    if (!my_hosts_access(&req))//判断主机是否具有访问权限

    {//如果主机没有被赋予给予权限,,则拒绝连接

      /*

        This may be stupid but refuse() includes an exit(0)

        which we surely don't want...

        clean_exit() - same stupid thing ...

      */

      syslog(deny_severity, "refused connect from %s",

         my_eval_client(&req));

 

      /*

        C++ sucks (the gibberish in front just translates the supplied

        sink function pointer in the req structure from a void (*sink)();

        to a void(*sink)(int) if you omit the cast, the C++ compiler

        will cry...

      */

      if (req.sink)

        ((void (*)(int))req.sink)(req.fd);

 

      (void) shutdown(new_sock, SHUT_RDWR);//关闭连接

      (void) closesocket(new_sock);

      continue;

    }

      }

    }

#endif /* HAVE_LIBWRAP */

 

    {

      size_socket dummyLen;

      struct sockaddr_storage dummy;

      dummyLen = sizeof(dummy);

      if (  getsockname(new_sock,(struct sockaddr *)&dummy,

                  (SOCKET_SIZE_TYPE *)&dummyLen)

      {

    sql_perror("Error on new connection socket");

    (void) shutdown(new_sock, SHUT_RDWR);

    (void) closesocket(new_sock);

    continue;

      }

    }

 

    /*

    ** Don't allow too many connections

    */

 

    if (!(thd= new THD))//为该连接分配处理的结构,在以后用于给线程使用

    {

      (void) shutdown(new_sock, SHUT_RDWR);

      (void) closesocket(new_sock);

      continue;

    }

    if (!(vio_tmp=vio_new(new_sock,

              sock == unix_sock ? VIO_TYPE_SOCKET :

              VIO_TYPE_TCPIP,

              sock == unix_sock ? VIO_LOCALHOST: 0)) ||

    my_net_init(&thd->net,vio_tmp))//初始化网络

    {

      /*

        Only delete the temporary vio if we didn't already attach it to the

        NET object. The destructor in THD will delete any initialized net

        structure.

      */

      if (vio_tmp && thd->net.vio != vio_tmp)

        vio_delete(vio_tmp);

      else

      {

    (void) shutdown(new_sock, SHUT_RDWR);

    (void) closesocket(new_sock);

      }

      delete thd;

      continue;

    }

    if (sock == unix_sock)

      thd->security_ctx->host=(char*) my_localhost;

 

    create_new_thread(thd);//准备为连接分配线程

  }

  DBUG_VOID_RETURN;

}

linux

Verwandte Etiketten:
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage