Welcome 微信登录

首页 / 数据库 / MySQL / MySQL 服务器监听客户端连接源码

在下面的代码有,有些结构体还不清楚,如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 < 0)    {      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 < socket_count; ++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 < MAX_ACCEPT_RETRY; 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) < 0  )      {    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;}MySQL 从接收连接到执行连接命令的一个源码流程MySQL新增一个连接源码相关资讯      MySQL教程 
  • 30分钟带你快速入门MySQL教程  (02月03日)
  • MySQL教程:关于I/O内存方面的一些  (01月24日)
  • CentOS上开启MySQL远程访问权限  (01/29/2013 10:58:40)
  • MySQL教程:关于checkpoint机制  (01月24日)
  • MySQL::Sandbox  (04/14/2013 08:03:38)
  • 生产环境MySQL 5.5.x单机多实例配  (11/02/2012 21:02:36)
本文评论 查看全部评论 (0)
表情: 姓名: 字数