#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define MAXLINE 80
#define SERV_PORT 8888
#define OPEN_MAX 1024
void perr_exit(const char *s)
{
perror(s);
exit(1);
}
int main(int argc, char *argv[])
{
char buf[MAXLINE];
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in cliaddr, servaddr;
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
listen(listenfd, 20);
int efd = epoll_create(OPEN_MAX);
if (efd == -1)
perr_exit("epoll_create");
struct epoll_event ev, ep[OPEN_MAX];
ev.events = EPOLLIN;
ev.data.fd = listenfd;
int res = epoll_ctl(efd, EPOLL_CTL_ADD, listenfd, &ev);
if (res == -1)
perr_exit("epoll_ctl");
while(1)
{
// 阻塞监听, 多路I/O复用,反应堆是一颗平衡二叉树
int nready = epoll_wait(efd, ep, OPEN_MAX, -1);
if (nready == -1)
{
perr_exit("epoll_wait");
}
// 解复用,O(log2n)
for (int i = 0; i < nready; i++)
{
if (! (ep[i].events & EPOLLIN))
{
continue;
}
if (ep[i].data.fd == listenfd)
{
socklen_t clilen = sizeof(cliaddr);
int connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
char str[INET_ADDRSTRLEN];
printf("Received msg ip: %s port: %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
ev.events = EPOLLIN;
ev.data.fd = connfd;
res = epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &ev);
if (res == -1)
{
perr_exit("epoll_ctl");
}
}
else
{
int sockfd = ep[i].data.fd;
ssize_t n = read(sockfd, buf, MAXLINE);
if (n == 0)
{
res = epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL);
if (res == -1)
{
perr_exit("epoll_ctl");
}
close(sockfd);
printf("Client %d closed\n", sockfd);
}
else
{
for (int j = 0; j < n; j++)
{
buf[j] = toupper(buf[j]);
}
write(sockfd, buf, n);
}
}
}
}
close(listenfd);
close(efd);
return 0;
}