您好,登錄后才能下訂單哦!
在C++中,使用Socket庫進(jìn)行網(wǎng)絡(luò)編程時(shí),通常需要一個(gè)事件循環(huán)來處理客戶端和服務(wù)器之間的通信
以下是一個(gè)簡單的基于Socket庫的事件循環(huán)示例:
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
class EventLoop {
public:
EventLoop() : stop_(false) {
worker_ = std::thread(&EventLoop::run, this);
}
~EventLoop() {
{
std::unique_lock<std::mutex> lock(mutex_);
stop_ = true;
}
cond_.notify_one();
if (worker_.joinable()) {
worker_.join();
}
}
void add_socket(int sockfd) {
std::unique_lock<std::mutex> lock(mutex_);
sockets_.push_back(sockfd);
}
void remove_socket(int sockfd) {
std::unique_lock<std::mutex> lock(mutex_);
sockets_.erase(std::remove(sockets_.begin(), sockets_.end(), sockfd), sockets_.end());
}
void run() {
while (true) {
std::vector<int> read_sockets;
std::vector<int> write_sockets;
{
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock, [this] { return !sockets_.empty() || stop_; });
for (int sockfd : sockets_) {
int events = 0;
if (FD_ISSET(sockfd, &read_fds_)) {
events |= POLLIN;
}
if (FD_ISSET(sockfd, &write_fds_)) {
events |= POLLOUT;
}
if (events) {
read_sockets.push_back(sockfd);
}
}
}
for (int sockfd : read_sockets) {
handle_read(sockfd);
}
for (int sockfd : write_sockets) {
handle_write(sockfd);
}
}
}
private:
void handle_read(int sockfd) {
char buffer[1024];
ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
if (n > 0) {
buffer[n] = '\0';
std::cout << "Received from " << sockfd << ": " << buffer << std::endl;
} else if (n == 0) {
remove_socket(sockfd);
close(sockfd);
} else {
perror("recv");
remove_socket(sockfd);
close(sockfd);
}
}
void handle_write(int sockfd) {
const char* message = "Hello, World!";
ssize_t n = send(sockfd, message, strlen(message), 0);
if (n > 0) {
remove_socket(sockfd);
close(sockfd);
} else {
perror("send");
remove_socket(sockfd);
close(sockfd);
}
}
std::thread worker_;
std::vector<int> sockets_;
std::mutex mutex_;
std::condition_variable cond_;
bool stop_;
fd_set read_fds_;
fd_set write_fds_;
};
int main() {
EventLoop loop;
int server_sock = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock == -1) {
perror("socket");
return 1;
}
struct sockaddr_in server_addr = {0};
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(8080);
if (bind(server_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
return 1;
}
if (listen(server_sock, 10) == -1) {
perror("listen");
return 1;
}
struct sockaddr_in client_addr = {0};
socklen_t client_addr_size = sizeof(client_addr);
int client_sock = accept(server_sock, (struct sockaddr*)&client_addr, &client_addr_size);
if (client_sock == -1) {
perror("accept");
return 1;
}
loop.add_socket(client_sock);
loop.run();
close(client_sock);
close(server_sock);
return 0;
}
這個(gè)示例中,我們創(chuàng)建了一個(gè)名為EventLoop
的類,它使用一個(gè)線程來運(yùn)行事件循環(huán)。事件循環(huán)使用select
函數(shù)來監(jiān)視多個(gè)套接字,當(dāng)某個(gè)套接字準(zhǔn)備好進(jìn)行讀/寫操作時(shí),相應(yīng)的事件處理函數(shù)將被調(diào)用。在這個(gè)示例中,我們只處理了讀和寫事件,但在實(shí)際應(yīng)用中,你可能需要處理更多類型的事件,例如連接建立、斷開連接等。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。