视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
MySQL服务器监听客户端连接源码
2020-11-09 12:03:09 责编:小采
文档

在下面的代码有,有些结构体还不清楚,如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 < 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;

}

下载本文
显示全文
专题