#include "head.h"
/*功能:将传入的文件描述符进行非阻塞处理
*newfd:需要处理发文件描述符
*返回值:空
*/
void set_nonblock(int newfd)
{
int flags = fcntl(newfd,F_GETFL);
flags |= O_NONBLOCK;
fcntl(newfd,F_SETFL,flags);
printf("fcctl ok\n");
}
/*功能:将文件描述符功能进行修改
*epollid:句柄描述符
*newfd:需要更改事件的描述符
*a:读或写
*b:是否开启ET模式
*返回值:空
*/
void mod_fd(int epollid,int newfd,bool a,bool b)
{
struct epoll_event eve;
bzero(&eve,sizeof(eve));
eve.data.fd = newfd;
if(a == true)
eve.events = EPOLLIN;
if(a == false)
eve.events = EPOLLOUT;
if(b == true)
eve.events |= EPOLLET;
epoll_ctl(epollid,EPOLL_CTL_MOD,newfd,&eve);
set_nonblock(newfd);
}
/*功能:将文件描述符加入epoll句柄描述符中,由句柄描述符树管理,并将描述符置为可读,选择是否开启ET模式
*epollid:句柄描述符
*newfd:需要由句柄描述符统一管理的新描述符
*a:true 或 false 开启ET模式
*返回值:空
*/
void add_fd(int epollid,int newfd,bool a)
{
struct epoll_event eve;
bzero(&eve,sizeof(eve));
eve.data.fd = newfd;
eve.events = EPOLLIN;
if(a == true)
{
eve.events |= EPOLLET;
}
epoll_ctl(epollid,EPOLL_CTL_ADD,newfd,&eve);
set_nonblock(newfd);
}
/*功能:LT模式下的读写
*epollid:句柄文件描述符
*sockid:socket文件描述符
*ret:正在发生的事件个数
*eve:事件结构体地址
*返回值:空
*/
void epoll_lt(int epollid,int sockid,int ret,struct epoll_event *eve)
{
int i;
struct sockaddr_in cli;
bzero(&cli,sizeof(cli));
int len = sizeof(struct sockaddr_in);
for(i = 0;i < ret;i++)
{
int tmpid = eve[i].data.fd;
printf("%d\n",eve[i].events);
printf("tmpid--->%d\n",tmpid);
if(tmpid == sockid)
{
int newfd = accept(sockid,(struct sockaddr *)&cli,&len);
printf("newfd--->%d\n",newfd);
if(newfd < 0)
sys_error("accept failed");
printf("client port:%d client ip:%s\n",ntohs(cli.sin_port),inet_ntoa(cli.sin_addr));
add_fd(epollid,newfd,false);
}
else if(eve[i].events &EPOLLIN)
{
char buf[10];
bzero(buf,10);
int ret = read(tmpid,buf,10);
if(ret < 0)
{
perror("read failed\n");
close(tmpid);
break;
}
if(ret == 0)
{
printf("client exit\n");
close(tmpid);
break;
}
printf("来自客户端:%s\n",buf);
}
else
{
printf("不可能走这里的\n");
}
}
}
/*功能:ET模式下的读写
*epollid:句柄文件描述符
*sockid:socket文件描述符
*ret:正在发生的事件个数
*eve:事件结构体地址
*返回值:空
*/
void epoll_et(int epollid,int sockid,int ret,struct epoll_event *eve)
{
int i;
struct sockaddr_in cli;
bzero(&cli,sizeof(cli));
int len = sizeof(struct sockaddr_in);
for(i = 0;i < ret;i++)
{
int tmpid = eve[i].data.fd;
printf("%d\n",eve[i].events);
printf("tmpid--->%d\n",tmpid);
if(tmpid == sockid)
{
int newfd = accept(sockid,(struct sockaddr *)&cli,&len);
printf("newfd--->%d\n",newfd);
if(newfd < 0)
sys_error("accept failed");
printf("client port:%d client ip:%s\n",ntohs(cli.sin_port),inet_ntoa(cli.sin_addr));
add_fd(epollid,newfd,true);
}
else if(eve[i].events & EPOLLIN)
{
while(1)
{
char buf[10];
bzero(buf,10);
int ret = read(tmpid,buf,10);
if(ret < 0)
{
if((errno == EAGAIN || errno == EWOULDBLOCK))
{
printf("read later\n");
break;
}
close(tmpid);
break;
}
if(ret == 0)
{
close(tmpid);
break;
}
printf("来自客户端:%s\n",buf);
}
mod_fd(epollid,tmpid,false,true);
}
else if(eve[i].events & EPOLLOUT)
{
char cmd[10] = "hello";
write(tmpid,cmd,strlen(cmd));
mod_fd(epollid,tmpid,true,true);
}
else
{
printf("不可能走这里的\n");
}
}
}
/*功能:绑定传入的端口与ip返回一个socket的文件描述符
*ip:ip地址
*port:端口号
*返回值:socket的文件描述符
*/
int server_init(char *ip,char *port)
{
int sockid = socket(AF_INET,SOCK_STREAM,0);
if(sockid < 0)
sys_error("sock failed");
struct sockaddr_in ser;
bzero(&ser,sizeof(ser));
ser.sin_family = AF_INET;
ser.sin_port = htons(atoi(port));
ser.sin_addr.s_addr = inet_addr(ip);
int ret = bind(sockid,(struct sockaddr *)&ser,sizeof(ser));
if(ret < 0)
sys_error("bind failed");
ret = listen(sockid,128);
return sockid;
}
/*功能:主函数
*argc:命令字符串个数
*argv:命令字符串的地址
*返回值:Int类型
*/
int main (int argc,char *argv[])
{
if(argc != 3)
{
printf("usage:%s <iP> <port>\n",argv[0]);
exit(1);
}
int sockid = server_init(argv[1],argv[2]);
printf("sockid--->%d\n",sockid);
struct epoll_event eve[MAX_EVE];
bzero(eve,MAX_EVE);
int epollid = epoll_create(5);
printf("epollid--->%d\n",epollid);
if(epollid < 0)
sys_error("epoll_create failed");
add_fd(epollid,sockid,true);
printf("listen ok\n");
while(1)
{
printf("******************\n");
int ret = epoll_wait(epollid,eve,MAX_EVE,-1);
printf("ret:%d\n",ret);
if(ret < 0)
sys_error("epoll_wait failed");
epoll_et(epollid,sockid,ret,eve);
// epoll_lt(epollid,sockid,ret,eve);
}
close(sockid);
return 0;
}