您好,登錄后才能下訂單哦!
在C++中,使用Socket庫進行網絡編程時,通常需要一個事件循環來處理客戶端和服務器之間的通信
以下是一個簡單的基于Socket庫的事件循環示例:
#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;
}
這個示例中,我們創建了一個名為EventLoop
的類,它使用一個線程來運行事件循環。事件循環使用select
函數來監視多個套接字,當某個套接字準備好進行讀/寫操作時,相應的事件處理函數將被調用。在這個示例中,我們只處理了讀和寫事件,但在實際應用中,你可能需要處理更多類型的事件,例如連接建立、斷開連接等。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。