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

文章来源:http://blog.csdn.net/wuyuxing24/article/details/48758927

一, 背景

       先说下我要实现的功能,server端一直在linux平台下面跑,当客户端有请求过来的时候server端接受到请求,拿到客户端的数据,根据拿到的数据做出相应的处理,得到处理的结果直接把结果数据发送给客户端。这样一个连接的请求结束,我的不是长连接的情况,不会一直保持客户端的连接。来一个处理一个处理完了就结束了。

二,源码下载(包括客户端测试代码)

  1. 我把逻辑处理部分简单化了,如果这份代码对你们有用的话,可以自己实现逻辑处理部分。
  2. 代码是要传入参数的,端口
  3. 代码我已经在Linux下面编译过了,也测试号了,因为代码中用到了数据库,如果你没有编译过可能要在Linux下装MySQL数据库。

    源码下载地址

三,代码的简单介绍

  • socket接受线程:C语言为了高并发所以选择了epoll。当程序启动的时候(g_net_update.c文件中main函数,会启动一个thread见函数create_accept_task)这个thread就处理一件事情,只管接收客户端的连接,当有连接进来的时候 通过epoll_ctl函数,把socket fd 加入到epoll里面去,epoll设置监听事件EPOLLIN | EPOLLET; 主要是监听的是加入到epoll中的socket是否可读(因为我的需求是客户端连上了server就会马上向server发送一份数据的)。其它的部分在主线程中处理。

  • 主线程:是一个无线循环,epoll_wait 函数相当于把客户端的连接从epoll中拿出来(因为我们监听的是EPOLLIN | EPOLLET)说明这个时候客户端有数据发送过来)。再通过recv_buffer_from_fd 函数把客户端发送过来的数据读出来。然后其他的一切就抛给线程池去处理。

  • 线程池:(代码中我会在池里面创建15个线程) 双向链表。加入线程就是在链表后面加一个链表项,链表的前面会一个一个被拿出来处理。主要是malloc 函数free函数,sem_wait函数sem_post的处理(sem_wait 会阻塞当值大于0是会减一,sem_post是值加一)。typedef void* (FUNC)(void arg, int index);是我们自定义的线程的逻辑处理部分,arg是参数,index是第几个线程处理(我们隐形的给每个线程都标了号),例如代码中的respons_stb_info,更加具体可以看看代码里面是怎么实现的。聪明的你也可以改掉这块的内容改成动态线程池,当某个时刻的处理比较多的时候能够动态的增加线程,而不像我代码里面的是固定的。

  • 数据库连接池:按照我的需求在处理客户端请求数据的时候是要访问数据库的。就是一下子创建出一堆的数据连接。要访问数据库的时候先去数据库连接池中找出空闲的连接,具体可以看下代码。使用的时候可以参考下database_process.c文件(代码中数据库连接池和线程池中的个数是一样的)。这里我想说下get_db_connect_from_pool这个函数,我用了随机数,我是为了不想每次都从0开始去判断哪个连接没有用到。为了数据库连接池中的每个链接都能等概率的使用到,具体的还是可以看下代码的实现。

  • log文件,代码中是可以自动保存log信息到文件中去的,具体可以看下代码。

四,碰到的一些问题和解决办法

  • 最初的时候server程序跑起来占掉了linux 90%多的使用率,因为是我们在create_accept_task 中socket没有设置成阻塞的。

  • server经常碰到一些莫名其妙的死机,没办法用了core dump 去抓死机的堆栈信息看在哪个函数死机的。

  • 在处理数据库的时候有的数据会自动的断掉(说是说8个小时) 后来采用的办法是每次都先mysql_ping一次让他重新连接上。

    就说几点吧,其实还有好多其他的就不说了。

五,在Linux下面用到的几个命令

  • ./server程序名 & //加&后台运行。

  • killall server程序名 // 停掉server的运行。要在server目录下面执行

  • netstat -antp|grep :端口号 // 查看端口下的socket状态

  • ps -eaf | grep server程序名 // 检查程序是否在运行,不过我一般是netstat -antp|grep :端口号 来看程序是否在运行。

好了 就到这里吧,如果你想实现java的高并发可以稍微看下 Linux java + apache mina + maven 实现高并发服务器


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用epoll线程池实现高并发服务器C++11代码示例: ```cpp #include <iostream> #include <thread> #include <vector> #include <queue> #include <mutex> #include <condition_variable> #include <sys/epoll.h> #include <unistd.h> #define MAX_EVENTS 100 #define THREAD_POOL_SIZE 10 std::mutex mtx; std::condition_variable cv; std::queue<int> taskQueue; void workerThread() { while (true) { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, [] { return !taskQueue.empty(); }); int fd = taskQueue.front(); taskQueue.pop(); // 处理任务,这里可以根据具体需求进行处理 lock.unlock(); // 继续监听其他事件 } } int main() { // 创建epoll句柄 int epoll_fd = epoll_create(1); if (epoll_fd == -1) { std::cerr << "Failed to create epoll" << std::endl; return 1; } // 创建线程池 std::vector<std::thread> threadPool; for (int i = 0; i < THREAD_POOL_SIZE; ++i) { threadPool.emplace_back(workerThread); } // 添加监听事件到epoll句柄 struct epoll_event event; event.events = EPOLLIN; event.data.fd = /* 监听的文件描述符 */; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, /* 监听的文件描述符 */, &event) == -1) { std::cerr << "Failed to add event to epoll" << std::endl; return 1; } // 开始监听事件 struct epoll_event events[MAX_EVENTS]; while (true) { int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (num_events == -1) { std::cerr << "Failed to wait for events" << std::endl; return 1; } for (int i = 0; i < num_events; ++i) { if (events[i].events & EPOLLIN) { // 处理读事件,将任务添加到任务队列 std::lock_guard<std::mutex> lock(mtx); taskQueue.push(events[i].data.fd); cv.notify_one(); } } } // 清理资源 close(epoll_fd); for (auto& thread : threadPool) { thread.join(); } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值