1 Star 0 Fork 0

wangshengkaiguoguo/Linux

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
01 6.54 KB
一键复制 编辑 原始数据 按行查看 历史
wangshengkaiguoguo 提交于 2024-07-22 13:23 . add 01.
#include <func.h>
#include <sys/epoll.h>
#define EPOLLEVENT_SIZE 1024
typedef struct conn_info
{
int fd;//保存文件描述符
int lastTime;//保存上一次交互时的时间
}ConnInfo_t;
int main()
{
//1. 创建TCP的监听套接字
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
printf("listenfd: %d\n", listenfd);
if(listenfd < 0) {
perror("socket");
return -1;
}
//设置套接字的属性:网络地址可以重用
int on = 1;
int ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if(ret < 0) {
perror("setsockopt");
close(listenfd);
return -1;
}
//2. 绑定网络地址
struct sockaddr_in serveraddr;
//初始化操作,防止内部有脏数据
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;//指定IPv4
serveraddr.sin_port = htons(8888);//指定端口号
//指定IP地址
serveraddr.sin_addr.s_addr = inet_addr("192.168.30.129");
ret = bind(listenfd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr));
if(ret < 0) {
perror("bind");
close(listenfd);//关闭套接字
return -1;
}
//3. 进行监听
ret = listen(listenfd, 10);
if(ret < 0) {
perror("listen");
close(listenfd);
return -1;
}
printf("server start listening.\n");
//创建epoll的实例
int epfd = epoll_create1(0);
printf("epfd:%d\n", epfd);
if(epfd < 0) {
perror("epoll_create1");
return -1;
}
struct epoll_event ev;
memset(&ev, 0, sizeof(ev));
ev.events = EPOLLIN;
ev.data.fd = listenfd;
//将要监听的listenfd和事件添加到内核上的红黑树上
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);
if(ret < 0) {
perror("epoll_ctl");
return -1;
}
ConnInfo_t conns[EPOLLEVENT_SIZE] = {0};
int curTime = 0;
struct epoll_event * pEvntArr = (struct epoll_event*)calloc(EPOLLEVENT_SIZE, sizeof(struct epoll_event));
while(1)
{
int nready = epoll_wait(epfd, pEvntArr, EPOLLEVENT_SIZE, 1000);
//printf("nready: %d\n", nready);
if(nready < 0) {
perror("epoll_wait");
return -1;
}
for(int i = 0; i < nready; ++i) {
int readyfd = pEvntArr[i].data.fd;
//处理新连接的请求
if(readyfd == listenfd) {
if(pEvntArr[i].events & EPOLLIN) {
//4. 接收新的连接
struct sockaddr_in peerAddr;
socklen_t len = sizeof(struct sockaddr_in);
int peerfd = accept(listenfd, (struct sockaddr*)&peerAddr, &len);
if(peerfd < 0) {
perror("accept");
close(listenfd);
return -1;
}
//将peerfd设置为非阻塞
int flags = fcntl(peerfd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(peerfd, F_SETFL, flags);
//正常情况,将新连接添加到epoll的监听红黑树中
struct epoll_event evt;
memset(&evt, 0, sizeof(evt));
evt.events = EPOLLIN;
evt.data.fd = peerfd;
ret = epoll_ctl(epfd, EPOLL_CTL_ADD, peerfd, &evt);
if(ret < 0) {
perror("epoll_ctl");
return -1;
}
printf("peerfd: %d\n", peerfd);
printf("client: %s:%d\n",
inet_ntoa(peerAddr.sin_addr),
ntohs(peerAddr.sin_port));
for(int j = 0; j < EPOLLEVENT_SIZE; ++j) {
if(conns[j].fd == 0) {
conns[j].fd = peerfd;
//保存连接建立时的时间
conns[j].lastTime = time(NULL);
break;
}
}
}
} else {
if(pEvntArr[i].events & EPOLLIN) {
//已经创建好的连接,接收数据
printf("readyfd read events happen.\n");
char buff[128] = {0};
ret = recv(readyfd, buff, sizeof(buff), 0);
printf("recv %d bytes,msg: %s\n", ret, buff);
if(ret == 0) {
printf("conn %d byebye.\n", readyfd);
//从监听的红黑树上删除
struct epoll_event evt;
memset(&evt, 0, sizeof(evt));
evt.events = EPOLLIN;
evt.data.fd = readyfd;
ret = epoll_ctl(epfd, EPOLL_CTL_DEL, readyfd, &evt);
if(ret < 0) {
perror("epoll_ctl");
return -1;
}
close(readyfd);
for(int j = 0; j < EPOLLEVENT_SIZE; ++j) {
if(conns[j].fd == readyfd) {
conns[j].fd = 0;
}
}
}
//回显操作
send(readyfd, buff, strlen(buff), 0);
//交互完成,更新lastTime
for(int j = 0; j < EPOLLEVENT_SIZE; ++j) {
if(conns[j].fd == readyfd) {
conns[j].lastTime = time(NULL);
break;
}
}
}
}
}
//进入下一次循环之前,判断是否有连接超过10秒钟未交互
curTime = time(NULL);
for(int j = 0; j < EPOLLEVENT_SIZE; ++j) {
if(conns[j].fd > 0 && (curTime - conns[j].lastTime > 10)) {
close(conns[j].fd);
printf("conn %d has timeout.\n", conns[j].fd);
ev.data.fd = conns[j].fd;
epoll_ctl(epfd, EPOLL_CTL_DEL, conns[j].fd, &ev);
ERROR_CHECK(epfd, -1, "epoll_ctl");
conns[j].fd = 0;//从conns数组中删除
}
}
}
close(listenfd);
return 0;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/wangshengkaiguoguo/linux.git
git@gitee.com:wangshengkaiguoguo/linux.git
wangshengkaiguoguo
linux
Linux
master

搜索帮助