✅ 整体结构
ThreadPool:一个线程池类,包含任务队列和工作线程。
Server:简易 TCP 服务器,接收连接后把已连接 socket 加入线程池任务队列。
main:启动服务器并运行线程池。
#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <unistd.h>
#include <netinet/in.h>
#include <string.h>
class ThreadPool {
public:
ThreadPool(size_t numThreads) : stop(false) {
// 启动 numThreads 个线程
for (size_t i = 0; i < numThreads; ++i) {
workers.emplace_back([this]() {
while (true) {
std::function<void()> task;
{ // 获取任务
std::unique_lock<std::mutex> lock(this->queue_mutex);
this->condition.wait(lock, [this]() {
return this->stop || !this->tasks.empty();
});
if (this->stop && this->tasks.empty())
return;
task = std::move(this->tasks.front());
this->tasks.pop();
}
task(); // 执行任务
}
});
}
}
// 添加任务
void enqueue(std::function<void()> task) {
{
std::unique_lock<std::mutex> lock(queue_mutex);
tasks.push(std::move(task));
}
condition.notify_one();
}
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for (std::thread &worker : workers)
worker.join();
}
private:
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
std::atomic<bool> stop;
};
// 简易 TCP 服务器函数
void start_server(int port, ThreadPool& pool) {
int server_fd, new_socket;
sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
server_fd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
bind(server_fd, (struct sockaddr *)&address, sizeof(address));
listen(server_fd, 10);
std::cout << "Server listening on port " << port << "...\n";
while (true) {
new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);
// 把任务加入线程池
pool.enqueue([new_socket]() {
char buffer[1024] = {0};
read(new_socket, buffer, 1024);
std::cout << "Received: " << buffer << std::endl;
std::string response = "Echo: ";
response += buffer;
send(new_socket, response.c_str(), response.size(), 0);
close(new_socket);
});
}
}
int main() {
ThreadPool pool(4); // 创建线程池,4 个线程
start_server(8080, pool); // 启动 TCP 服务器
return 0;
}
使用Epoll
#include <iostream>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "ThreadPool.h"
#define MAX_EVENTS 1024
#define PORT 8080
// 设置非阻塞
int setNonBlocking(int fd) {
int flags = fcntl(fd, F_GETFL);
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
int main() {
ThreadPool pool(4); // 线程池
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in addr {};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(PORT);
bind(server_fd, (sockaddr*)&addr, sizeof(addr));
listen(server_fd, 128);
setNonBlocking(server_fd);
int epfd = epoll_create1(0);
epoll_event ev{}, events[MAX_EVENTS];
ev.data.fd = server_fd;
ev.events = EPOLLIN; // 可读事件
epoll_ctl(epfd, EPOLL_CTL_ADD, server_fd, &ev);
std::cout << "Server listening on port " << PORT << "...\n";
while (true) {
int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
for (int i = 0; i < nfds; ++i) {
int fd = events[i].data.fd;
if (fd == server_fd) {
// 新连接
sockaddr_in client_addr{};
socklen_t client_len = sizeof(client_addr);
int client_fd = accept(server_fd, (sockaddr*)&client_addr, &client_len);
setNonBlocking(client_fd);
epoll_event client_ev{};
client_ev.data.fd = client_fd;
client_ev.events = EPOLLIN | EPOLLET; // 边缘触发(高效)
epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &client_ev);
} else {
// 客户端可读,把任务扔给线程池
int client_fd = fd;
pool.enqueue([client_fd]() {
char buffer[1024] = {0};
int bytes = read(client_fd, buffer, sizeof(buffer));
if (bytes <= 0) {
close(client_fd); // 客户端断开
return;
}
std::cout << "Recv: " << buffer << std::endl;
std::string response = "Echo: ";
response += buffer;
send(client_fd, response.c_str(), response.size(), 0);
});
}
}
}
close(server_fd);
close(epfd);
return 0;
}