1 Star 0 Fork 3

xjm/轻量级高性能C++ webserver

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
main.cpp 4.22 KB
一键复制 编辑 原始数据 按行查看 历史
滕宇 提交于 2021-08-16 01:43 . 提交yuserver文件夹
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include "locker.h"
#include "threadpool.h"
#include "http_conn.h"
#include <iostream>
using namespace std;
#define MAX_FD 65536
#define MAX_EVENT_NUMBER 10000
//
extern void addfd(int epollfd, int fd, bool one_shot); // 在http_conn.cpp中
extern void removefd(int epollfd, int fd); // 在http_coon.cpp中
//
void addsig(int sig, void(handler)(int)){ // handler回调函数,用来处理信号
struct sigaction sa;
memset(&sa, '\0', sizeof(sa));
sa.sa_handler =handler;
sigfillset(&sa.sa_mask);
assert(sigaction(sig, &sa, NULL) != -1);
}
int main(int argc, char* argv[]){
if(argc<=1){
cout<<"正确格式:"<<argv[0]<<" "<<"端口号"<<endl;
return 1;
}
int port = atoi(argv[1]);
addsig(SIGPIPE, SIG_IGN);
threadpool<http_conn>* pool = nullptr; // TODO
try{
pool=new threadpool<http_conn>;
}catch(...){ // catch(...)省略号的作用是表示捕获所有类型的异常
return 1;
}
http_conn* users=new http_conn[MAX_FD];
// 创建套接字http://c.biancheng.net/view/2131.html
int listenfd=socket(PF_INET, SOCK_STREAM, 0);
int ret=0;
struct sockaddr_in address; // 后续bind操作
address.sin_addr.s_addr=INADDR_ANY; // INADDR_ANY转换过来是0.0.0.0→泛指本机,表示本机的所有IP(因为有些机器有多张网卡)
address.sin_family=AF_INET; // ipv4
address.sin_port=htons(port);
// 端口复用
int reuse=1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); //
ret=bind(listenfd, (struct sockaddr*)&address, sizeof(address));
ret=listen(listenfd, 5);
// 创建epoll对象,创建事件数组,添加
epoll_event events[MAX_EVENT_NUMBER]; // 数组名→events,数组元素→epoll_event结构体
int epollfd=epoll_create(5);
// 添加到epoll对象中
addfd(epollfd, listenfd, false);
http_conn::m_epollfd=epollfd; // 所有socket上的事件都被注册到同一个epoll内核事件中,所以设置成静态的
while(true){
int number=epoll_wait(epollfd, events, MAX_EVENT_NUMBER, -1); // 发生的事件数
if((number<0) && (errno!=EINTR)){ // 如果read()读到数据为0,那么就表示文件读完了,如果在读的过程中遇到了中断则read()应该返回-1,同时置errno为EINTR
cout<<"epoll调用失败"<<endl;
break;
}
for(int i=0;i<number;i++){
int sockfd=events[i].data.fd;
if(sockfd==listenfd){ // 监听到了什么
struct sockaddr_in client_address;
socklen_t client_addrlength=sizeof(client_address);
int connfd=accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength);
if(connfd<0){ // connfd存储accept函数的返回值
cout<<"errno is: "<<errno<<endl;
continue;
}
if(http_conn::m_user_count>=MAX_FD){ // user_count>=65536
close(connfd);
continue;
}
users[connfd].init(connfd, client_address); // http_conn数组
}else if(events[i].events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR)){
users[sockfd].close_conn();
}else if(events[i].events & EPOLLIN){ // EPOLLIN事件
if(users[sockfd].read()){ // bool read();// 非阻塞读
pool->append(users+sockfd); // users是数组指针,可以当做数组名使用,这里将指定的http_conn加入到线程池中
}else{
users[sockfd].close_conn();
}
}else if(events[i].events & EPOLLOUT){ // 对于EPOLLOUT: 如果状态改变了[比如 从满到不满],只要输出缓冲区可写就会触发
if(!users[sockfd].write()){
users[sockfd].close_conn();
}
}
}
}
close(epollfd);
close(listenfd);
delete[] users;
delete pool;
return 0;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/xujingmeng/webserver.git
git@gitee.com:xujingmeng/webserver.git
xujingmeng
webserver
轻量级高性能C++ webserver
master

搜索帮助