双向链表实现线程池 用于TCP并发连接

如何实现一个百万并发量的TCP服务器 朋友问我:你现在年薪百万吗?我说:我没有,倒是并发量超百万的服务器可以有(坏笑)。实现一个并发量超一百万的TCP服务器使用epoll获取请求+线程池处理请求四台虚拟机(一个服务端以及三个服务端) 服务端硬件配置要求:双核处理器,4G运行内存 客服端硬件配置要求:单核处理器,2G运行内存 虚拟机运行操作系统:ubuntu server 64位 虚拟机软件:VMware Fusion 操作系统:macOS 阅读详情

简述:自我感觉对C指针了解的还是比较透彻,能够运用自如,一方面练习一下多线程编程,另一方面练习一下数据结构链表。

但是完成的过程中,各种问题还是扑面而来,共花了2个小时完成了此线程池来实现TCP并发连接,创建固定数目的线程

时间仓促,可能有某些指针未释放,或者还没完善的地方,希望能共同讨论。

双向链表提高扫描速度,信号等待用while保护,防止惊群,在任务提取和加入过程动态维护链表,防止链表过长和冗余。

创建线程,初始化属性为DETEACH,避免人为对子线程的回收。



#include "unp.h"
#include <assert.h>
typedef struct demytask {							/*任务*/
	//void 				*(*func)(void *arg);			/*套接字处理函数指针*/
	void					*data;						/*连接套接字*/
	struct demytask		*next;						/*后向索引*/
	struct demytask		*prev;						/*后向索引*/
}task;
typedef struct pool {
	pthread_mutex_t 	mutex;				/*锁和条件*/
	pthread_cond_t	cond;
	int				nthreads;			/*线程池中线程数*/
	int				totaltasks;			/*线程池中总的任务数*/
	int				runtasks;			/*正在服务的任务数*/
	int				shut;				/*线程池关闭状态*/
	int				waittasks;			/*等待空闲线程的任务数*/
	task				*head;				/*任务头指针*/
	task				*tail;				/*任务尾指针*/
	/*pthread_t	*threads*/				/*线程ID数组,暂无用*/
}thread_pool;

thread_pool	*pool;						/*线程池指针*/

void *thread_func(void *arg);			/*线程函数*/
void inital_thread_poll(int num);		/*线程池初始化*/
void insert_task_2_poll(/*void *(*func)(void *),*/ void *data);/*增加任务*/
void del_task_2_poll();				/*删除任务*/
void serve_machine(int connfd) ;		/*为客户端服务函数*/
void clear_pool(int	signo) ;			/*线程池资源释放*/


	
int inital_thread_poll(int num) {
    pthread_attr_t      attr;
    pthread_t       pid;
    int                 i, err;
    pool = (thread_pool *)malloc(sizeof(thread_pool));  /*在堆上分配*/
    if(pool == NULL) {
    #ifdef PRT
        PST("Malloc error");
    #endif
        return -1;
    }
    assert(pool != NULL);
    pthread_mutex_init( &(pool->mutex), NULL);      /*锁*/
    pthread_cond_init( &(pool->cond), NULL);        /*条件*/
    pool->nthreads = num;           
    pool->totaltasks = pool->runtasks = 0;      /*当前总接受的任务数和运行任务数*/
    pool->shut = 0;                                                     /*关闭标志*/
    pool->head = pool->tail = NULL;
    pool->head = pool->tail = malloc(sizeof(task));     /*初始化头尾指针*/          
    pthread_attr_init( &attr);                      /*属性*/
    pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED);
    for( i =0; i < num; i++) {
        if((err = pthread_create( &pid, &attr, thread_func, NULL)) != 0) {  /*创建线程*/
            return err;
        }
    }
    pthread_attr_destroy( &attr);
    return 0;
}
/*
*给线程池中加入任务
*/
void insert_task_2_poll(/*void *(*func)(void *),*/ void *data) { /*添加任务*/
    task *mytask;
    mytask = (task *)malloc(sizeof(task));          /*在堆上分配*/
    if(mytask == NULL) {
    #ifdef PRT
        PST("Malloc task error");
    #endif 
        return;
    }
/*  mytask->func = func;*/
    mytask->data = data;
    pthread_mutex_lock(&(pool->mutex));
    pool->tail->next = mytask;
    mytask->prev = pool->tail;
    pool->tail = mytask;
    pool->tail->next = NULL;
    pool->totaltasks ++;                        /*任务数加1*/
    pool->waittasks ++;                     /*等待处理的任务数加1*/
#ifdef PRT
        printf("Add a task ,the total tasks is %d, waittask is %d\n",pool->totaltasks,pool->waittasks);
#endif
    pthread_cond_signal(&(pool->cond));/*唤醒等待任务的线程*/
    pthread_mutex_unlock(&(pool->mutex));
    return;
}
/*
*删除线程池中尾任务
*/
void del_task_2_poll() {                /*删除任务*/
/*  pthread_mutex_lock(&(pool->mutex));*/
    free(pool->tail->data);
    pool->tail->data = NULL;
    pool->tail = pool->tail->prev;
    free(pool->tail->next);
    pool->tail->next = NULL;
    pool->totaltasks --;
#ifdef PRT
        printf("Delete a task ,the total tasks is %d, waittask is %d\n",pool->totaltasks,pool->waittasks);
#endif
/*  pthread_mutex_lock(&(pool->mutex));*/
}
/*
*线程函数
*/
void *thread_func(void *arg) {              /*等待任务,无则阻塞*/
    /*void  *(*functemp)(void *);*/
    int     connfd;
    for( ; ;) {
        pthread_mutex_lock(&(pool->mutex));
        while(pool->waittasks == 0) 
            pthread_cond_wait(&(pool->cond), &(pool->mutex));
    /*  functemp = pool->tail->func;*/
        connfd = *((int *)(pool->tail->data));
        pool->runtasks ++;                  /*处理过的任务数*/
        pool->waittasks --;                 /*等待处理的任务数*/
        del_task_2_poll();                      /*释放这个任务*/
        pthread_mutex_unlock(&(pool->mutex));   /*解锁,使其他线程可以等待其他任务*/
        serve_machine(&connfd);             /*任务开始执行*/
    }
}
/*
*释放线程池资源
*/
void clear_pool(int signo) {                /*清除线程池*/
    task    *temp;
#ifdef PRT
    printf("\n服务器正在关闭...\n");
#endif
    pthread_mutex_lock(&(pool->mutex));
    temp = pool->head->next;
    for(; temp != NULL; temp = pool->head->next) {
        free(pool->head->data);
        pool->head->data = NULL;
        if(pool->head->prev != NULL){
            free(pool->head->prev);
            pool->head->prev = NULL;
        }
        free(pool->head);
        pool->head = NULL;
        pool->head = temp;
    }
    /*free(temp);*/
    pthread_mutex_unlock(&(pool->mutex));
    pthread_mutex_destroy(&(pool->mutex));
    pthread_cond_destroy(&(pool->cond));
    free(pool);
    pool = NULL;
    exit(0);
}




int main(int argc, char **argv)
{
	int					listenfd, *connfd, num;
	socklen_t				clilen;
	struct sockaddr_in		cliaddr, servaddr;
	const int 				on = 1;
	if( argc != 2)
		err_quit("argc");
	listenfd = Socket(AF_INET, SOCK_STREAM, 0);
	num = atoi(argv[1]);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family      = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(SERV_PORT);
	setsockopt(listenfd,SOL_SOCKET, SO_REUSEADDR, &on,	sizeof(int));
	Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
	inital_thread_poll(num);						/*初始化线程池*/
	signal(SIGINT,clear_pool);						/*中断时,释放资源*/
	Listen(listenfd, LISTENQ);
	for ( ; ; ) {
		clilen = sizeof(struct sockaddr);
		connfd = (int * )malloc(sizeof(int));				/*每个连接一个*/
		*connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
		 insert_task_2_poll(connfd);				/*增加任务,投入到线程池*/
	}
	clear_pool(SIGINT);
	exit(0);
}


Apache服务器本质:一个可定制的TCP连接处理网关 Web服务器本质上是运行在TCP之上的应用层网关,其核心能力在于高效管理并发连接与协议无关的数据转发。Apache的设计哲学并非专为HTTP而生,而是以MPM(多路处理模块)为底盘,通过事件驱动、线程/进程抽象和钩子机制,实现连接接入、分发与响应输出的解耦。这种架构使其兼具HTTP服务、反向代理、AJP网关等多重角色,技术价值体现在资源复用性、模块可插拔性及高并发下的稳定性。典型应用场景包括静态文件托管、PHP/FastCGI后端集成、HTTPS卸载及长连接代理。本文深入解析Apache作为通用网络通信网关 阅读详情

相关推荐

多线程实现双向链表增删改

多线程实现双向链表的增删改 其中的信号量设成一个也行- -

【Java并发编程】AQS使用双向链表

AQS为什么使用双向链表

weixin_48302711的博客 415

线程安全型双向链表的实现

操作系统c++编程实现安全型双向链表,线程的创建,利用线程对链表进行增删改操作,并检验结果是否正确

并发编程(2)——AQS

AQS如何实现,及其底层为什么这样设计

weixin_43046131的博客 549

C++双向链表类及四种多线程安全读写测试用例

实现双向链表,查找、替换、删除、插入,并用线程同步技术实现了多线程读写与线程安全

线程安全双向链表源代码

线程安全双向链表实现2次检验,中间包含3个线程,代码完善。可以vs与vc++运行,没有问题

双向链表以及栈和队列实现

双向链表:可选支持带多线程锁链表可以实现 队列和栈等常用数据结构提示:以下是本篇文章正文内容,下面案例可供参考双线链表c实现,可以多线程运行。

qq_37077309的博客 673

操作系统课设-线程安全的双向链表

原创手操,操作系统课设,线程安全的双向链表,VC6.0,无须配置,可运行

使用c语言实现双向链表

C是你必须要学的一门编程语言,但可能不是第一门。

了迹奇有没 715

FOC实战笔记:RC吸收电路的设计考量与参数调优

本文深入探讨了FOC驱动器中RC吸收电路的设计与调优。针对MOS管开关过程中的电压尖峰问题,详细阐述了RC电路的钳位与能量吸收原理,并提供了从参数计算、实验调试到布局布线的完整实战指南,旨在帮助工程师有效提升系统可靠性与稳定性。

weixin_29219539的博客 276

windows版kafka异常java.nio.file.FileSystemException另一个程序正在使用此文件,进程无法访问

环境 现象 原因 解决方法 参考

山水牧羊 3847

C语言实现双向链表的增删查改

定义一个带头节点的双向链表需要一个数据域两个指针域,其中一个next指针是指向当前节点的下一个节点,另外一个prev指针是指向当前节点的前一个节点。如下图所示: 该头结点本质上只是一个傀儡节点并无实际用处,带头节点的好处就是我们在实际操作链表时不用考虑头指针的指向。而双向链表的前后指针域也大大方便了我们对于链表的实际操作。 代码示例: DBlinklist.h文件 #pragma ...

小心眼儿猫的博客 3614

Dify工作流自动化:如何用Trae AI助手10倍提升你的开发效率(含避坑指南)

本文详细介绍了如何利用Trae AI助手自动化生成Dify工作流,实现开发效率的10倍提升。通过构建DSL示例库、精准需求描述和四步实战法,开发者可将重复的配置工作交给AI,快速生成可运行的工作流,并提供了关键的避坑指南。

weixin_29062865的博客 370

基于Netty实现TCP连接的服务端、客户端

简介 Netty是一个异步事件驱动的网络应用框架,可快速开发可维护的高性能协议服务器和客户端。基于NIO实现的高性能网络IO框架,极大简化基于常用网络协议的编程(TCP、UDP等)。 架构模型 完整版: 根据自己的理解,简单版的工作模型架构图: 如上图所示,Netty是基于主从Reactor的架构模型;主EventLoopGroup负责处理客户端的连接请求事件,客户端连接成功后交由从EventLoopGroup,具体的数据IO由从EventLoopGroup的EventLoop处理。 EventLoop

cocoawork 丶的博客 1万+

S7-1200PLC 2轴直线插补详细算法(完整源代码)

速度轴V90PN总线伺服梯形加减速速度控制(标准报文1应用)_v90伺服加减速时间怎么调整-优快云博客文章浏览阅读288次。

RXXW_Dor的博客 4259

PMO与供应链管理的整合:端到端项目交付的优化策略

在当今全球化和市场竞争日益激烈的环境中,组织面临着前所未有的项目复杂性和交付压力。传统上相互独立的项目管理办公室(PMO)与供应链管理(SCM)正逐渐意识到:只有通过无缝整合,才能实现真正高效的端到端项目交付。本文深入探讨了PMO与供应链管理整合的战略价值、核心框架和实施路径,通过生动的比喻、实际案例和实用工具,展示了如何打破部门壁垒,构建协同高效的项目生态系统。无论您是PMO负责人、供应链专业人士还是高级管理层,都将从本文获得重塑项目交付模式、优化资源利用、降低风险并提升组织竞争力的宝贵见解和行动指南。

项目管理的博客 948

Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池)

文章来源:http://blog.youkuaiyun.com/wuyuxing24/article/details/48758927 一, 背景        先说下我要实现的功能,server端一直在linux平台下面跑,当客户端有请求过来的时候server端接受到请求,拿到客户端的数据,根据拿到的数据做出相应的处理,得到处理的结果直接把结果数据发送给客户端。这样一个连接的请求结束,我

$firecat利白的代码足迹$ 1660

【QCA6174】QCA6174 DFS认证的时候会有概率信道不会跳转的情况,通常跳转成功概率只有25%问题分析及解决方案

Master设备需要测试的项目。

wgl307293845的博客 752

基于 epoll + 线程池的 C/S 架构网盘设计

epoll 的是一个联合体,既可以存一个fd,也可以存一个ptr指针。本项目选择存指针,把每个 socket 相关的上下文封装成一个myevent_s// 事件结构:每个 socket 对应一个int fd;// cfd 或 listenfd// epoll_create 句柄int events;int status;// 1 表示在监听树中,0 表示不在// 回指网络层对象,方便线程函数访问// 上监听树:根据 status 决定是 ADD 还是 MODint op;

ljh2304060615的博客 451

lammps教程:FeNiCr合金多晶结构建模方法

大家好,我是小马老师。 本文介绍合金多晶模型的建模过程,使用的软件为Atomsk。 Atomsk是一个开源软件,可运行在windows、linux等多种操作系统上,本文使用windows版的Atomsk实现建模,其他操作系统的建模命令基本相同。 建模过程如下: 1. 生成单晶Fe晶胞 atomsk --create fcc 3.65 Fe Fe.xsf 2. 建立多晶节点文件polycrystal.txt 新建一个文本文件polycrystal.txt,文件内容为: box 200 100 200 ran

lammps_jiayou的博客 6658

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Java实习模拟面试之唯品会一面:HashMap、并发安全、Spring循环依赖、MySQL索引与MVCC、JVM、TCP详解

这场唯品会 Java 一面模拟涵盖了集合、并发、Spring、MySQL、JVM、网络六大核心模块,问题层层深入,尤其注重原理理解和细节追问。不仅要记住结论,更要理解“为什么”;多画图(如 B+ 树、三次握手、三级缓存);结合源码和实际场景思考。💡最后提醒:面试不是背题,而是展示你的技术思维和学习能力。扎实基础 + 清晰表达 = Offer!关注我,获取更多 Java 面试干货!

吾为热爱计科,致力于知识分享的践行者,此博客是我在这条道路上留下的足迹。 909

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C++高并发Web服务器实战:从Reactor到Proactor的架构设计与实现

网络编程是现代软件开发的核心技能之一,其本质是通过操作系统提供的套接字接口实现进程间通信。在Linux环境下,epoll作为高效的I/O多路复用机制,通过事件驱动模型管理大量并发连接,解决了传统阻塞I/O的性能瓶颈。结合线程池技术,能够将计算密集型任务与I/O操作解耦,显著提升系统吞吐量。这种架构模式在需要高并发处理的场景中具有重要价值,例如实时通信系统、在线交易平台和内容分发网络。本文以C++轻量级Web服务器为例,深入解析半同步/半反应堆线程池模型的设计原理,探讨Reactor与模拟Proactor两种

379

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

网络开发中客户端连接保鲜机制实现方法

网络开发中的TCP连接分为长连接模式和短连接的模式,短连接就是在服务端接收到客户端请求,完成处理和应答后会主动关闭这个连接,而长连接顾名思义就是这个连接会一直存在着。一般来说,短链接的程序更容易编写和维护,因为一旦收到断开消息表明当前请求结束了,新的请求也会重新发起新的连接,而长连接需要处理拆包,粘包,错误累计飘移等各种复杂的问题。不过有得必有失,短链接最主要的问题是性能问题,每个请求都需要做三次

lhh1113的博客 549

Java面试全攻略(基础 + 集合 + 并发 + JVM + 框架)

Java面试核心考察内容主要包括:1)基础语法与面向对象2)集合框架(尤其是HashMap)3)并发编程与线程池4)JVM内存与垃圾回收5)Spring与MyBatis框架6)计算机网络基础。

2301_79783364的博客 408

Linux Http服务器 epoll + threadpool 实现

Http服务器中包含了http协议、TCP/IP协议,同时该项目又包含了I/O复用技术、多进程多线程、线程池管理以及Linux gdb多线程多进程调试等一系列基本操作,所以通过该项目可以把以上的技术点一一掌握,博主也是本着这样的初心来进行本 HttpServe 的开发设计。 首先,亮出 github地址:https://github.com/GUOQIFU/GuoQi_HttpServe 传送门 首先,分为三大部分:1. Http 报文解析 2. epoll反应堆 3.线程池的设计 1. Http 报文解析

GUO-QI的博客 1958
上一篇: 简单进程池实现多TCP客户服务
下一篇: 简易ping程序
七绝乌梭
博客等级 码龄18年 5粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值