Thttpd源程序解析14 连接过程详解

2024-03-14 16:59

本文主要是介绍Thttpd源程序解析14 连接过程详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

经过前面讲述Thttpd源程序每个函数的大致的功能,现在针对Thttpd如何共做接收用户的连接请求的详细过程。

当服务器正常运行的时候将会不断的根据用户设置的服务器的IP地址类型调用handle_newconnect函数进行对有连接请求的处理。handle_newconnect函数是处理用户的连接请求的主要函数。

handle_newconnect函数

handle_newconnect函数是一个死循环的函数:

(1)判断当前的连接数量是否超过了设置的最大的连接数量,如果是调用tmr_run函数执行时间hash表中超时的处理函数然后返回0;如果不是继续执行

(2)判断下一个可以使用的文件描述符是否可以使用,对于不可以使用的异常退出程序,对于可以使用的继续执行后面的过程

(3)获取下一个可以使用的连接对象的地址。

(4)判断下一个连接对象的连接地址是否分配过,对于分配过的直接执行后面的程序,对于没有分配过的进行内存分配,如果分配失败直接异常退出程序对于分配成功的继续执行后面的过程。

(5)调用httpd_get_conn函数根据返回结果进行处理:返回值为GC_FAIL(0)调用tmr_run函数执行时间hash表中超时的处理函数然后返回0,返回值为GC_NO_MORE(2)返回1,其他继续执行后面的程序。

(6)初始化连接对象的参数,更新下一个可以使用的对象在数组中的地址以及当前连接数。

(7)设置此文件描述符为非阻塞模式

(8)将此文件描述符添加至检测的文件描述符数组中。

static int handle_newconnect( struct timeval* tvP, int listen_fd )
{connecttab* c;ClientData client_data;/* This loops until the accept() fails, trying to start new** connections as fast as possible so we don't overrun the** listen queue.*/for (;;){/* Is there room in the connection table? */if ( num_connects >= max_connects ){/* Out of connection slots.  Run the timers, then the** existing connections, and maybe we'll free up a slot** by the time we get back here.*/syslog( LOG_WARNING, "too many connections!" );tmr_run( tvP );return 0;}/* Get the first free connection entry off the free list. */if ( first_free_connect == -1 || connects[first_free_connect].conn_state != CNST_FREE ){syslog( LOG_CRIT, "the connects free list is messed up" );exit( 1 );}c = &connects[first_free_connect];/* Make the httpd_conn if necessary. */if ( c->hc == (httpd_conn*) 0 ){c->hc = NEW( httpd_conn, 1 );if ( c->hc == (httpd_conn*) 0 ){syslog( LOG_CRIT, "out of memory allocating an httpd_conn" );exit( 1 );}c->hc->initialized = 0;++httpd_conn_count;}/* Get the connection. */switch ( httpd_get_conn( hs, listen_fd, c->hc ) ){/* Some error happened.  Run the timers, then the** existing connections.  Maybe the error will clear.*/case GC_FAIL:tmr_run( tvP );return 0;/* No more connections to accept for now. */case GC_NO_MORE:return 1;}c->conn_state = CNST_READING;/* Pop it off the free list. */first_free_connect = c->next_free_connect;c->next_free_connect = -1;++num_connects;client_data.p = c;c->active_at = tvP->tv_sec;c->wakeup_timer = (Timer*) 0;c->linger_timer = (Timer*) 0;c->next_byte_index = 0;c->numtnums = 0;/* Set the connection file descriptor to no-delay mode. */httpd_set_ndelay( c->hc->conn_fd );fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ );++stats_connections;if ( num_connects > stats_simultaneous ){stats_simultaneous = num_connects;}}
}

httpd_get_conn函数

httpd_get_conn 函数是真正接受请求的处理函数,并未相关的请求对象重新分配内存空间,初始化连接参数

(1)判断请求是否初始化过,对于没有初始化过的重新为请求的对象的相关参数分配内存空间。

(2)调用accept函数接受用户请求。

(3)根据接受请求的返回值判断接受请求是否成功,如果失败返回GC_FAIL(0),如果成功继续执行后面的程序。

(4)判断客户端的IP地址类型是否有效,如果无效返回GC_FAIL(0),如果成功继续执行后面的程序。

(5)初始化相关的连接对象参数。

int httpd_get_conn( httpd_server* hs, int listen_fd, httpd_conn* hc )
{httpd_sockaddr sa;socklen_t sz;if ( ! hc->initialized ){hc->read_size = 0;httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 );hc->maxdecodedurl =hc->maxorigfilename = hc->maxexpnfilename = hc->maxencodings =hc->maxpathinfo = hc->maxquery = hc->maxaccept =hc->maxaccepte = hc->maxreqhost = hc->maxhostdir =hc->maxremoteuser = hc->maxresponse = 0;
#ifdef TILDE_MAP_2hc->maxaltdir = 0;
#endif /* TILDE_MAP_2 */httpd_realloc_str( &hc->decodedurl, &hc->maxdecodedurl, 1 );httpd_realloc_str( &hc->origfilename, &hc->maxorigfilename, 1 );httpd_realloc_str( &hc->expnfilename, &hc->maxexpnfilename, 0 );httpd_realloc_str( &hc->encodings, &hc->maxencodings, 0 );httpd_realloc_str( &hc->pathinfo, &hc->maxpathinfo, 0 );httpd_realloc_str( &hc->query, &hc->maxquery, 0 );httpd_realloc_str( &hc->accept, &hc->maxaccept, 0 );httpd_realloc_str( &hc->accepte, &hc->maxaccepte, 0 );httpd_realloc_str( &hc->reqhost, &hc->maxreqhost, 0 );httpd_realloc_str( &hc->hostdir, &hc->maxhostdir, 0 );httpd_realloc_str( &hc->remoteuser, &hc->maxremoteuser, 0 );httpd_realloc_str( &hc->response, &hc->maxresponse, 0 );
#ifdef TILDE_MAP_2httpd_realloc_str( &hc->altdir, &hc->maxaltdir, 0 );
#endif /* TILDE_MAP_2 */hc->initialized = 1;}/* Accept the new connection. */sz = sizeof(sa);hc->conn_fd = accept( listen_fd, &sa.sa, &sz );if ( hc->conn_fd < 0 ){if ( errno == EWOULDBLOCK ){return GC_NO_MORE;}/* ECONNABORTED means the connection was closed by the client while** it was waiting in the listen queue.  It's not worth logging.*/if ( errno != ECONNABORTED ){syslog( LOG_ERR, "accept - %m" );}return GC_FAIL;}if ( ! sockaddr_check( &sa ) ){syslog( LOG_ERR, "unknown sockaddr family" );close( hc->conn_fd );hc->conn_fd = -1;return GC_FAIL;}(void) fcntl( hc->conn_fd, F_SETFD, 1 );hc->hs = hs;(void) memset( &hc->client_addr, 0, sizeof(hc->client_addr) );(void) memmove( &hc->client_addr, &sa, sockaddr_len( &sa ) );hc->read_idx = 0;hc->checked_idx = 0;hc->checked_state = CHST_FIRSTWORD;hc->method = METHOD_UNKNOWN;hc->status = 0;hc->bytes_to_send = 0;hc->bytes_sent = 0;hc->encodedurl = "";hc->decodedurl[0] = '\0';hc->protocol = "UNKNOWN";hc->origfilename[0] = '\0';hc->expnfilename[0] = '\0';hc->encodings[0] = '\0';hc->pathinfo[0] = '\0';hc->query[0] = '\0';hc->referrer = "";hc->useragent = "";hc->accept[0] = '\0';hc->accepte[0] = '\0';hc->acceptl = "";hc->cookie = "";hc->contenttype = "";hc->reqhost[0] = '\0';hc->hdrhost = "";hc->hostdir[0] = '\0';hc->authorization = "";hc->remoteuser[0] = '\0';hc->response[0] = '\0';
#ifdef TILDE_MAP_2hc->altdir[0] = '\0';
#endif /* TILDE_MAP_2 */hc->responselen = 0;hc->if_modified_since = (time_t) -1;hc->range_if = (time_t) -1;hc->contentlength = -1;hc->type = "";hc->hostname = (char*) 0;hc->mime_flag = 1;hc->one_one = 0;hc->got_range = 0;hc->tildemapped = 0;hc->first_byte_index = 0;hc->last_byte_index = -1;hc->keep_alive = 0;hc->should_linger = 0;hc->file_address = (char*) 0;return GC_OK;
}

 

 

这篇关于Thttpd源程序解析14 连接过程详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/809080

相关文章

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

最新版IDEA配置 Tomcat的详细过程

《最新版IDEA配置Tomcat的详细过程》本文介绍如何在IDEA中配置Tomcat服务器,并创建Web项目,首先检查Tomcat是否安装完成,然后在IDEA中创建Web项目并添加Web结构,接着,... 目录配置tomcat第一步,先给项目添加Web结构查看端口号配置tomcat    先检查自己的to

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

Linux内核之内核裁剪详解

《Linux内核之内核裁剪详解》Linux内核裁剪是通过移除不必要的功能和模块,调整配置参数来优化内核,以满足特定需求,裁剪的方法包括使用配置选项、模块化设计和优化配置参数,图形裁剪工具如makeme... 目录简介一、 裁剪的原因二、裁剪的方法三、图形裁剪工具四、操作说明五、make menuconfig

详解Java中的敏感信息处理

《详解Java中的敏感信息处理》平时开发中常常会遇到像用户的手机号、姓名、身份证等敏感信息需要处理,这篇文章主要为大家整理了一些常用的方法,希望对大家有所帮助... 目录前后端传输AES 对称加密RSA 非对称加密混合加密数据库加密MD5 + Salt/SHA + SaltAES 加密平时开发中遇到像用户的

SpringBoot集成SOL链的详细过程

《SpringBoot集成SOL链的详细过程》Solanaj是一个用于与Solana区块链交互的Java库,它为Java开发者提供了一套功能丰富的API,使得在Java环境中可以轻松构建与Solana... 目录一、什么是solanaj?二、Pom依赖三、主要类3.1 RpcClient3.2 Public