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

相关文章

将Mybatis升级为Mybatis-Plus的详细过程

《将Mybatis升级为Mybatis-Plus的详细过程》本文详细介绍了在若依管理系统(v3.8.8)中将MyBatis升级为MyBatis-Plus的过程,旨在提升开发效率,通过本文,开发者可实现... 目录说明流程增加依赖修改配置文件注释掉MyBATisConfig里面的Bean代码生成使用IDEA生

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

C#数据结构之字符串(string)详解

《C#数据结构之字符串(string)详解》:本文主要介绍C#数据结构之字符串(string),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录转义字符序列字符串的创建字符串的声明null字符串与空字符串重复单字符字符串的构造字符串的属性和常用方法属性常用方法总结摘

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处