热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

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

{

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) <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;

}

linux

推荐阅读
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 软件测试行业深度解析:迈向高薪的必经之路
    本文深入探讨了软件测试行业的发展现状及未来趋势,旨在帮助有志于在该领域取得高薪的技术人员明确职业方向和发展路径。 ... [详细]
  • 如何在Django框架中实现对象关系映射(ORM)
    本文介绍了Django框架中对象关系映射(ORM)的实现方式,通过ORM,开发者可以通过定义模型类来间接操作数据库表,从而简化数据库操作流程,提高开发效率。 ... [详细]
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • CRZ.im:一款极简的网址缩短服务及其安装指南
    本文介绍了一款名为CRZ.im的极简网址缩短服务,该服务采用PHP和SQLite开发,体积小巧,约10KB。本文还提供了详细的安装步骤,包括环境配置、域名解析及Nginx伪静态设置。 ... [详细]
  • 如何将955万数据表的17秒SQL查询优化至300毫秒
    本文详细介绍了通过优化SQL查询策略,成功将一张包含955万条记录的财务流水表的查询时间从17秒缩短至300毫秒的方法。文章不仅提供了具体的SQL优化技巧,还深入探讨了背后的数据库原理。 ... [详细]
  • 解决JavaScript中法语字符排序问题
    在开发一个使用JavaScript、HTML和CSS的Web应用时,遇到从SQLite数据库中提取的法语词汇排序不正确的问题,特别是带重音符号的字母未按预期排序。 ... [详细]
  • 本文详细介绍了PostgreSQL与MySQL在SQL语法上的主要区别,包括如何使用COALESCE替代IFNULL、金额格式化的方法、别名处理以及日期处理等关键点。 ... [详细]
  • 从CodeIgniter中提取图像处理组件
    本指南旨在帮助开发者在未使用CodeIgniter框架的情况下,如何独立使用其强大的图像处理功能,包括图像尺寸调整、创建缩略图、裁剪、旋转及添加水印等。 ... [详细]
  • 在处理大数据量的SQL分页查询时,通常需要执行两次查询来分别获取数据和总记录数。本文介绍了一种优化方法,通过单次查询同时返回分页数据和总记录数,从而提高查询效率。 ... [详细]
  • java类名的作用_java下Class.forName的作用是什么,为什么要使用它?
    湖上湖返回与带有给定字符串名的类或接口相关联的Class对象。调用此方法等效于:Class.forName(className,true,currentLoader) ... [详细]
  • Logging all MySQL queries into the Slow Log
    MySQLoptionallylogsslowqueriesintotheSlowQueryLog–orjustSlowLog,asfriendscallit.However,Thereareseveralreasonstologallqueries.Thislistisnotexhaustive:Belowyoucanfindthevariablestochange,astheyshouldbewritteninth ... [详细]
  • flea,frame,db,使用,之 ... [详细]
  • 本文详细探讨了在Web开发中常见的UTF-8编码问题及其解决方案,包括HTML页面、PHP脚本、MySQL数据库以及JavaScript和Flash应用中的乱码问题。 ... [详细]
author-avatar
lovely夏的宠儿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有