libevent实现了对io多路复用函数的封装,复习一下linux下的io复用函数,select,poll,epoll
在c/s模型中,要处理多个客户端的请求以达到并发处理的效果,有以下几种方法
- 主线程accept,多线程处理,为每一个客户端开一个线程
- 主进程accept,多进程处理,为每一个客户端开一个进程
- 线程池/进程池,将程序执行过程中线程/进程的创建销毁开销放在程序一开始执行时进行,进一步可以动态改变池中线程/进程个数
- io多路复用函数,单线程模式
多线程模式的服务器模型大体如下
//server.cpp
#include <iostream>
#include <cerrno>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
void* process_client(void* arg);
int main()
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
std::cerr << "socket error" << std::endl;
return -1;
}
struct sockaddr_in servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(8080);
servaddr.sin_addr.s_addr = INADDR_ANY;
if(bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
{
close(sockfd);
std::cerr << "bind error" << std::endl;
return -1;
}
if(listen(sockfd, 10) < 0)
{
close(sockfd);
std::cerr << "listen error" << std::endl;
return -1;
}
struct sockaddr_in addr;
bzero(&addr, sizeof(addr));
socklen_t len = sizeof(addr);
while(true)
{
/* 主线程接受客户端请求,每一个子线程处理一个服务器与客户端的交互 */
int fd = accept(sockfd, (struct sockaddr*)&addr, &len);
pthread_t tid;
pthread_create(&tid, NULL, process_client, (void*)&fd);
pthread_detach(tid);
}
close(sockfd);
return 0;
}
void *process_client(void *arg)
{
int fd = *static_cast<int *>(arg);
char reply[] = "server has receive your message";
char msg[4096];
/* 每个线程一个循环 */
while(true)
{
bzero(msg, sizeof(msg));
int ret = recv(fd, msg, sizeof(msg), 0);
if(ret < 0)
{
continue;
}
else if(ret == 0)
{ std::cout << "close connection with client " << fd << std::endl;
close(fd);
pthread_exit(NULL);
break;
}
else
{
msg[ret] = '\0';
std::cout << "receive from client " << fd << " : " << msg << std::endl;
ret = send(fd, reply, strlen(reply), MSG_NOSIGNAL);
if(ret < 0)
{
continue;
}
else if(ret == 0)
{
std::cout << "close connection with client " << fd << std::endl;
close(fd);
pthread_exit(NULL);
break;
}
}
}
}
//client.cpp
#include <iostream>
#include <string>
#include <cerrno>