epoll的一个demo,备忘(epoll+线程池)

Linux QT Epoll 服务器Demo Linux下QT开发,网络服务器Demo,采用Epoll库 立即下载
/**
张亚霏修改

文件名:epoll_demo.c
编译: gcc epoll_demo.c -pthread


程序源码如下(请自行编辑宏定义SERVER_IP为自己的IP):
*/


/*Linux 2.6 x86_64 only*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <time.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>
#include <errno.h>

/*线程池的线程数量*/
#define THREAD_MAX 1

/*监听端口*/
#define LISTEN_PORT 8000

/*
监听端口的数量,从LISTEN_PORT到LISTEN_PORT+LISTEN_MAX-1
*/
#define LISTEN_MAX 1


#define SERVER_IP "127.0.0.1"


typedef struct
{
    char	ip4[128];
    int		port;
    int		fd;
} listen_info;



//服务器参数
static listen_info s_listens[LISTEN_MAX];

//线程池参数
static unsigned int s_thread_para[THREAD_MAX][8];//线程参数
static pthread_t s_tid[THREAD_MAX];//线程ID
pthread_mutex_t s_mutex[THREAD_MAX];//线程锁


//私有函数
static int init_thread_pool(void);
static int init_listen4(char *ip4, int port, int max_link);

//线程函数
void* test_server4(unsigned int thread_para[]);

int main(int argc, char *argv[])//客户端驱动
{
    //临时变量
    int            i, j, rc;

    int            sock_listen;    //监听套接字
    int            sock_cli;    //客户端连接
    int            listen_index;

    int            epfd;
    int			nfds;
    struct epoll_event    ev;
    struct epoll_event    events[LISTEN_MAX];

    socklen_t        addrlen;    //地址信息长度
    struct sockaddr_in    addr4;        //IPv4地址结构




    //线程池初始化
    rc = init_thread_pool();
    if (0 != rc)
	exit(-1);

    //初始化服务监听
    for (i = 0; i < LISTEN_MAX; i++)
    {
        sprintf(s_listens[i].ip4, "%s", SERVER_IP);
        s_listens[i].port = LISTEN_PORT + i;
        //创建监听
        rc = init_listen4(s_listens[i].ip4, s_listens[i].port, 64);
        if (0 > rc)
        {
            fprintf(stderr, "无法创建服务器监听于%s:%d\n", s_listens[i].ip4, s_listens[i].port);
            perror(NULL);
            exit(-1);
        }
        s_listens[i].fd = rc;
    }

    //设置集合
    epfd = epoll_create(8192);
    for (i = 0; i < LISTEN_MAX; i++)
    {
        //加入epoll事件集合
        ev.events = EPOLLIN;
        ev.data.u32 = i;//记录listen数组下标
        if (epoll_ctl(epfd, EPOLL_CTL_ADD, s_listens[i].fd, &ev) < 0)
        {
            fprintf(stderr, "向epoll集合添加套接字失败(fd =%d)\r\n", rc);
            exit(-1);
        }
    }


    //服务循环
    for ( ; ; )
    {
        //等待epoll事件
        nfds = epoll_wait(epfd, events, LISTEN_MAX, -1);
        //处理epoll事件
        for (i = 0; i < nfds; i++)
        {
            //接收客户端连接
            listen_index = events[i].data.u32;
            sock_listen = s_listens[listen_index].fd;
            addrlen = sizeof(struct sockaddr_in);
            bzero(&addr4, addrlen);
            sock_cli = accept(sock_listen, (struct sockaddr *)&addr4, &addrlen);
            if (0 > sock_cli)
            {
                fprintf(stderr, "接收客户端连接失败\n");
                continue;
            }
            //查询空闲线程对
            for (j = 0; j < THREAD_MAX; j++)
            {
                if (0 == s_thread_para[j][0]) break;
            }
            if (j >= THREAD_MAX)
            {
                fprintf(stderr, "线程池已满, 连接将被放弃\r\n");
                shutdown(sock_cli, SHUT_RDWR);
                close(sock_cli);
                continue;
            }
            //复制有关参数
            s_thread_para[j][0] = 1;//设置活动标志为"活动"
            s_thread_para[j][1] = sock_cli;//客户端连接
            s_thread_para[j][2] = listen_index;//服务索引
            //线程解锁
            pthread_mutex_unlock(s_mutex + j);
        }//end of for(i;;)
    }//end of for(;;)

    exit(0);
}

static int init_thread_pool(void)
{
    int    i, rc;

    //初始化线程池参数
    for (i = 0; i < THREAD_MAX; i++)
    {
        s_thread_para[i][0] = 0;//设置线程占用标志为"空闲"
        s_thread_para[i][7] = i;//线程池索引
        pthread_mutex_lock(s_mutex + i);//线程锁
    }

    //创建线程池
    for (i = 0; i < THREAD_MAX; i++)
    {
        rc = pthread_create(s_tid + i, 0, (void *)test_server4, (void *)(s_thread_para[i]));
        if (0 != rc)
        {
            fprintf(stderr, "线程创建失败\n");
            return(-1);
        }
    }

    //成功返回
    return(0);
}

static int init_listen4(char *ip4, int port, int max_link)
{
    //临时变量
    int            sock_listen4;
    struct sockaddr_in    addr4;
    unsigned int        optval;
    struct linger        optval1;

    //初始化数据结构
    bzero(&addr4, sizeof(addr4));
    inet_pton(AF_INET, ip4, &(addr4.sin_addr));
    addr4.sin_family = AF_INET;
    addr4.sin_port = htons(port);

    //创建SOCKET
    sock_listen4 = socket(AF_INET, SOCK_STREAM, 0);
    if (0 > sock_listen4) return(-1);

    //设置SO_REUSEADDR选项(服务器快速重起)
    optval = 0x1;
    setsockopt(sock_listen4, SOL_SOCKET, SO_REUSEADDR, &optval, 4);

    //设置SO_LINGER选项(防范CLOSE_WAIT挂住所有套接字)
    optval1.l_onoff = 1;
    optval1.l_linger = 60;
    setsockopt(sock_listen4, SOL_SOCKET, SO_LINGER, &optval1, sizeof(struct linger));

    if (0 > bind(sock_listen4, (struct sockaddr *)&addr4, sizeof(addr4)))
    {
        close(sock_listen4);
        return(-1);
    }

    if (0 > listen(sock_listen4, max_link))
    {
        close(sock_listen4);
        return(-1);
    }

    return(sock_listen4);
}


void * test_server4(unsigned int thread_para[])
{
    //临时变量
    int        pool_index;    //线程池索引
    int        sock_cli;    //客户端连接
    int        listen_index;    //监听索引

    char        buff[32768];    //传输缓冲区
    char        *p;
    int        i, j, len;

    //线程脱离创建者
    pthread_detach(pthread_self());
    pool_index = thread_para[7];

wait_unlock:

    pthread_mutex_lock(s_mutex + pool_index);//等待线程解锁

    //线程变量内容复制
    sock_cli = thread_para[1];//客户端连接
    listen_index = thread_para[2];//监听索引

    //接收请求
    len = recv(sock_cli, buff, 32768, MSG_NOSIGNAL);

    //构造响应
    p = buff;
    //HTTP头
    p += sprintf(p, "HTTP/1.1 200 OK\r\n");
    p += sprintf(p, "Content-Type: text/html\r\n");
    p += sprintf(p, "Connection: closed\r\n\r\n");
    //页面
    p += sprintf(p, "<html>\r\n<head>\r\n");
    p += sprintf(p, "<meta content=\"text/html; charset=GBK\" http-equiv=\"Content-Type\">\r\n");
    p += sprintf(p, "</head>\r\n");
    p += sprintf(p, "<body style=\"background-color: rgb(229, 229, 229);\">\r\n");

    p += sprintf(p, "<center>\r\n");
    p += sprintf(p, "<H3>连接状态</H3>\r\n");
    p += sprintf(p, "<p>服务器地址 %s:%d</p>\r\n", s_listens[listen_index].ip4, s_listens[listen_index].port);
    j = 0;
    for (i = 0; i < THREAD_MAX; i++)
    {
        if (0 != s_thread_para[i][0]) j++;
    }
    p += sprintf(p, "<H3>线程池状态</H3>\r\n");
    p += sprintf(p, "<p>线程池总数 %d 活动线程总数 %d</p>\r\n", THREAD_MAX, j);
    p += sprintf(p, "</center></body></html>\r\n");
    len = p - buff;

    //发送响应
    send(sock_cli, buff, len, MSG_NOSIGNAL);

    //释放连接
    shutdown(sock_cli, SHUT_RDWR);
    close(sock_cli);

    //线程任务结束
    thread_para[0] = 0;//设置线程占用标志为"空闲"
    goto wait_unlock;

    pthread_exit(NULL);
}

C语言长连接服务器Demo(epoll非阻塞) C语言长连接服务器Demo,TCP SOCKET利用epoll非阻塞,大大提升效率。只是一个简单的demo。 立即下载

相关推荐

CocosCreator3.8.2实战:5分钟搞定多分辨率适配与横竖屏自动翻转(附完整Demo)

本文针对CocosCreator3.8.2开发者,提供了一套5分钟快速集成、开箱即用的多分辨率屏幕适配与横竖屏自动翻转解决方案。通过封装好的ScreenAdapter组件,开发者无需处理复杂计算,即可实现等比缩放或拉伸全屏两种主流适配模式,并自动响应设备旋转,有效解决移动端UI在不同屏幕比例和方向下的显示问题。文末附完整Demo。

z4a5b6的博客 721

epoll的一个demo,备忘

[code="c"] /** 张亚霏修改 文件名:epoll_demo.c 编译: gcc epoll_demo.c -pthread 程序源码如下(请自行编辑宏定义SERVER_IP为自己的IP): */ /*Linux 2.6 x86_64 only*/ #include #include #include #include #inc...

kimi's blog 300

当爬虫遇到TikTok滑块:一份给开发者的verifyV2避坑指南与调试心得

本文详细解析了TikTok滑块验证码verifyV2的破解与优化策略,涵盖验证码触发机制、滑块图片获取、验证请求构造及高级调试技巧。通过实战案例和代码示例,帮助开发者有效应对复杂反爬机制,提升验证通过率。特别针对verifyV2系统的加密算法和轨迹模拟提供了专业解决方案。

weixin_30919429的博客 641

Android系统开发

Android系统开发 视频课程和源码的对应关系、下载方法请看"源码下载方法xxxxx.TXT" 视频和源码的对应关系:视频 源码第1课第1节_编写第1个Androi...

dieling4341的博客 1615

Win11/Win10系统下,Proe5.0 M280终极版保姆级安装与激活指南(含SSQ补丁避坑)

本文提供Win11/Win10系统下Pro/E 5.0 M280终极版的详细安装与激活指南,涵盖环境配置、SSQ补丁应用及常见问题解决方案。通过系统调整、分步安装和性能优化,确保软件在现代操作系统上的稳定运行,特别适合机械设计用户参考。

weixin_30895059的博客 440

直流电源滤波电路的设计与优化:从基础原理到高效应用

本文深入探讨直流电源滤波电路的设计与优化,从基础原理到高效应用全面解析。重点介绍电容滤波和电感滤波的工作原理及实战设计要点,分享复合滤波电路的进阶技巧,并提供常见问题排查指南。文章还涵盖现代滤波技术的新发展,如有源滤波和数字控制滤波的应用,帮助工程师提升电源系统的稳定性和效率。

weixin_29255731的博客 175

EPOLL + 事件驱动

#include <sys/eventfd.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <sys/epoll.h> #include <string.h> #include &l...

gaoyupeng123的专栏 729

基于STM32H5的循环GPDMA链表使用

STM32H503的GPDMA链表模式可实现灵活的数据传输。相比传统DMA直接编程方式,链表模式通过配置多个节点实现分散数据传输,支持循环链表功能。示例展示了如何使用GPDMA链表实现UART1循环发送数据:配置两个DMA节点分别指向不同发送缓冲区,构建循环链表并绑定到DMA通道。关键点包括:清空链表结构体、正确设置循环模式、检查节点配置。此方法提高了DMA使用的灵活性,适用于需要交替传输多段数据的场景。

kevin1499的博客 451

Linux 下使用epoll实现转发服务器的小DEMO

一个小DEMO.  I

Bottle 的专栏 1315

用 ABAP ADK 写一个可控的自建表归档程序:从选择屏幕到 ARCHIVE_SAVE_OBJECT 的完整链路

文章摘要: 本文介绍了SAP系统中数据归档的核心概念与实践方法。归档旨在将不常访问但需保留的数据从在线数据库移出,以减轻系统负载,同时满足合规要求。文章重点阐述了: 归档与备份、重组的本质区别 SAP归档框架的核心组件:归档对象(AOBJ)、归档管理界面(SARA)和ADK开发工具包 通过YAPTMAIN表示例,展示了完整的归档流程: 使用选择屏幕控制归档范围 管理归档会话 写入归档记录 生成统计报表 强调了归档程序设计中需要考虑的运维、审计和性能因素 该方案可有效解决自建日志表"悄悄长胖&quo

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 227

14、网络切片技术:原理、应用与挑战

本文详细探讨了网络切片技术的原理、应用场景及其在5G网络中的重要性。网络切片作为一种关键的网络架构技术,能够在同一物理网络上创建多个独立的逻辑网络,以满足不同应用对安全性、可靠性和性能的多样化需求。文章深入分析了网络切片在5G、SDN/NFV等技术背景下的发展与挑战,并探讨了其在制造业、交通运输、零售等多个行业的实际应用。此外,还介绍了网络切片的部署流程、未来发展趋势以及相关技术难点,为读者全面了解网络切片技术提供了有价值的参考。

palm99的专栏 253

linux驱动开发day6--(epoll实现IO多路复用、信号驱动IO、设备树以及节点和属性解析相关API使用)

红黑树、一张表以及三个接口、int epfd=epoll_create(int size--无意义,>0即可)----------成功:返回根节点对应文件描述符,失败:-1a.struct epoll_event event;定义事件结构体b.struct epoll_event events[10];定义存放就绪事件描述符的数组c.添加准备就绪事件进入epoll,如:event.events = EPOLLIN; // 读事件event.data.fd = fd1;epoll_ctl(epfd, EPOL

m0_72852022的博客 798

提示工程ROI计算模板:架构师私藏Excel表(含自动计算)

花3个人力优化提示词,到底能带来多少实际收益?“这个提示工程项目值得做吗?投入10万成本,多久能回本?“不同LLM应用的提示词优化优先级怎么排?全凭经验拍脑袋?当前90%的企业在提示工程投入上缺乏标准化的量化评估方法,导致资源浪费(盲目投入无回报项目)或错失机会(低估高价值优化点)。ROI = (总收益 - 总成本) / 总成本 × 100%对于提示工程,总成本=显性成本+隐性成本,总收益=直接收益+间接收益(后文会详细拆解)。提示工程的价值不是“玄学”,而是可以用数据量化的投资行为。本文分享的。

AI开发架构师 1073

【保姆级教程】从0到1入门Blender+MATLAB联动仿真(附完整代码+操作步骤)

本文介绍了Blender与MATLAB在三维建模与数值仿真中的联动方法。主要内容包括:1)前期准备,包括软件安装和联动原理;2)使用Blender搭建机械臂模型并导出FBX格式;3)MATLAB读取模型并实现动力学仿真。文章提供了完整代码和避坑指南,重点解决了模型导出格式兼容性和数据读取问题。该方法适用于课程设计和科研入门,具有零基础可复现的特点。同时提出了进阶方向,如复杂模型制作和闭环控制等。关键要点包括优先选择FBX格式、注意导出参数设置以及明确两软件的分工协作关系。

Lzzzznb的博客 530

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

数学建模论文排版全攻略:从工具选型到标准化工作流

文档排版是学术写作与工程报告中的基础环节,其核心在于通过样式定义、自动化编号与交叉引用等技术,实现内容结构与格式的统一管理。掌握高效的排版原理,不仅能大幅提升文档制作的专业性与一致性,更能将作者从繁琐的格式调整中解放出来,专注于核心内容的创作。这在需要严格遵循格式规范、且包含大量公式、图表与参考文献的数学建模、学术论文等场景中价值尤为凸显。本文聚焦数学建模论文这一典型应用,针对高频搜索的“MathType安装”与“WPS”等工具痛点,系统梳理了从文档编辑器、公式工具到图表绘制的选型避坑指南,并详解了一套基于

weixin_34279579的博客 455

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

数学建模竞赛论文写作全攻略:从摘要到排版的高分秘籍

数学建模是将现实问题抽象为数学问题并求解的核心方法,其关键在于通过算法和模型找到最优解。这一过程不仅锻炼逻辑思维与编程能力,其成果的呈现——即论文写作——更是将技术工作转化为可评估价值的关键环节。一篇优秀的建模论文需要遵循清晰的结构,从问题重述、模型建立、求解分析到评价推广,逻辑严密地展示整个解决方案。尤其在摘要部分,需用精炼语言概括模型方法与量化结果,这直接决定了评审的第一印象。本文聚焦于数学建模竞赛的论文撰写,深入剖析了摘要撰写、模型可视化、结果分析等核心模块的实战技巧与常见陷阱,旨在帮助参赛者将复杂的

weixin_34357436的博客 334

转 epoll的一个demo(epoll+线程池)

#include #include #include #include #include #include   #include #include #include #include   #define THREAD_MAX 20 #define LISTEN_MAX 20 #define SERVER_IP "127.0.0.1"   ty

zhaoxiaozheng1987的博客 580

Epoll的使用详解

1.EPOLL简介 EPOLL 的API用来执行类似poll()的任务。能够用于检测在多个文件描述符中任何IO可用的情况。Epoll API可以用于边缘触发(edge-triggered)和水平触发(level-triggered), 同时epoll可以检测更多的文件描述符。以下的系统调用函数提供了创建和管理epoll实例: epoll_create() 可以创建一个epoll实例并返回相应

Michael的博客 4237

linux下高性能网络框架epoll的通信小demo

高性能网络框架 epoll 的通信小 demoepoll 相关 API 介绍测试代码测试效果总结 epoll 相关 API 介绍 1.创建EPOLL 句柄 int epoll_create(int size); 2.向EPOLL对象中添加、修改或者删除感兴趣的事件 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); op取值:EPOLL_CTL_ADD 添加新的事件到epoll中 EPOLL_CTL_MOD

weixin_45825875的博客 914

epoll的示例demo和解析

【代码】epoll的示例demo和解析。

hahaha133456的博客 341

高并发的epoll+线程池,epoll在线程池内

文章来源:http://blog.chinaunix.net/uid-311680-id-2439723.html 我们知道,服务器并发模型通常可分为单线程和多线程模型,这里的线程通常是指“I/O线程”,即负责I/O操作,协调分配任务的“管理线程”,而实际的请求和任务通常交由所谓“工作者线程”处理。通常多线程模型下,每个线程既是I/O线程又是工作者线程。所以这里讨论的是,单I/O线程+多

$firecat利白的代码足迹$ 2822

C语言实现epoll简洁demo代码

等待监听的所有fd相应事件的产生。

fantasyYXQ的博客 867

【Epoll】Linux + C + Epoll实现高并发服务器(线程池 + 数据库连接池) --研读+实践

一, 背景 先说下我要实现的功能,server端一直在linux平台下面跑,当客户端有请求过来的时候server端接受到请求,拿到客户端的数据,根据拿到的数据做出相应的处理,得到处理的结果直接把结果数据发送给客户端。这样一个连接的请求结束,我的不是长连接的情况,不会一直保持客户端的连接。来一个处理一个处理完了就结束了。 二,源码下载(包括客户端测试代码) 我把逻辑处理部分简单化了,如果这份代码对你们有用的话,可以自己实现逻辑处理部分。 代码是要传入参数的,端口 代码我已经在Linux...

我的笔记本 2189

socket创建失败_linux下socket采用epoll编程demo

首先,需要调用epoll_create创建epoll; 此后我们就可以进行socket/bind/listen; 然后调用epoll_ctl进行注册; 接下来,就可以通过一个while(1)循环调用epoll_wait来等待事件的发生; 然后循环查看接收到的事件并进行处理; 1)如果事件是sever的socketfd我们就要进行accept,并且把接收到client的socketfd加入到要监听的...

weixin_39631467的博客 277

网络编程:epoll的demo

EpollServer.hpp #pragma once #include "tcpServer.hpp" #include <sys/epoll.h> #define NUM 20 #define SIZE 64 #define DFL -1 class Backage { public: Backage(int fd , int pos = 0) :_fd(fd) ,_pos(pos) { memset(_buf,0,

代码笔记本 1354

epoll与线程池实现的服务器端示例

[代码] [C/C++]代码 /* Linux 2.6 x86_64 only*/ #include   #include   #include   #include   #include   #include   #include   #include   #include #include     #define THREAD_MAX 20  #defin

zhyjunFov的专栏 1014
上一篇: 利用两个栈求解算数表达式的源代码
下一篇: 虚表结构与虚继承内存对象模型
执迷的信徒
博客等级 码龄16年 245粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值