#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include<sys/epoll.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
if(argc < 2)
{
printf("./a.out port\n");
exit(1);
}
// 创建socket
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd == -1)
{
printf("socket err");
exit(1);
}
// 设置端口复用
int flags = 1;
int opt = setsockopt(sfd, SOL_SOCKET, SO_REUSEPORT, &flags, sizeof(flags));
if(opt == -1)
{
perror("setsockopt err");
exit(1);
}
// 绑定 服务端 IP 和 port struct sockaddr_in server;
struct sockaddr_in server;
memset(&server, 0x00, sizeof(server));
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1]));
int ret = bind(sfd, (struct sockaddr *)&server, sizeof(server));
if(ret == -1)
{
perror("bind err");
exit(1);
}
// 设置监听
ret = listen(sfd, 128);
if(ret == -1)
{
perror("listen err");
exit(1);
}
// 客户端连接以及数据发送请求处理
struct sockaddr_in client;
socklen_t client_addr_len = sizeof(client);
// 创建eopll 树的根节点
int epfd = epoll_create(3000);
// 初始化 epoll 树
struct epoll_event ev;
ev.data.fd = sfd;
ev.events = EPOLLIN;
// 将服务端添加进 ePoll 树
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &ev);
if(ret == -1)
{
perror("epoll_ctl err");
exit(1);
}
struct epoll_event all[3000];
// epoll 与 客户端 连接、消息数据处理.
while(1)
{
// 委托 epoll 检查
int epno = epoll_wait(epfd, all, sizeof(all) / sizeof(all[0]), -1);
if(epno == -1)
{
perror("epoll_wait err");
exit(1);
}
// 遍历 委托检查返回的个数
for(int i = 0; i < epno; ++i)
{
int fd = all[i].data.fd;
// 判断是否有 新连接
if(fd == sfd)
{
printf("与客户端连接成功\n");
int cfd = accept(sfd, (struct sockaddr *)&client, &client_addr_len);
if(cfd == -1)
{
perror("accept err");
exit(1);
}
struct epoll_event temp;
temp.data.fd = cfd;
temp.events = EPOLLIN;
// 将得到的新连接 加入 epoll树
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, cfd, &temp);
if(ret == -1)
{
perror("epoll_ctl err + 95");
exit(1);
}
}
// 客户端是否发送数据
else
{
// 确保只产生 读 事件
if(!(all[i].events & EPOLLIN))
{
continue;
}
char buf[BUFSIZ] = {0};
ret = recv(fd, &buf, sizeof(buf), 0);
if(ret == -1)
{
perror("recv err");
exit(1);
}
else if(ret == 0)
{
printf("与客户端连接断开\n");
// 将 客户端 从 epoll 树删除
ret = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
if(ret == -1)
{
perror("epoll ctl del err");
exit(1);
}
close(fd);
}
else
{
printf("recv the data %s", buf);
send(fd, buf, ret, 0);
}
}
}
}
close(sfd);
return 0;
}
Linux简单epoll服务器
最新推荐文章于 2024-07-24 09:58:58 发布