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

相关文章

MySQL数据库双机热备的配置方法详解

《MySQL数据库双机热备的配置方法详解》在企业级应用中,数据库的高可用性和数据的安全性是至关重要的,MySQL作为最流行的开源关系型数据库管理系统之一,提供了多种方式来实现高可用性,其中双机热备(M... 目录1. 环境准备1.1 安装mysql1.2 配置MySQL1.2.1 主服务器配置1.2.2 从

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

MyBatis常用XML语法详解

《MyBatis常用XML语法详解》文章介绍了MyBatis常用XML语法,包括结果映射、查询语句、插入语句、更新语句、删除语句、动态SQL标签以及ehcache.xml文件的使用,感兴趣的朋友跟随小... 目录1、定义结果映射2、查询语句3、插入语句4、更新语句5、删除语句6、动态 SQL 标签7、ehc

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1