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

2014-11-24 18:11:21 · 作者: · 浏览: 2

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