前两章已经学习了epoll根据前两篇的学习,基本掌握了epoll事件,但对于同时监控读写事件还未涉及到,故作一次补充
server端
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int gSetNonblocking(int fd)
{
int old_option=fcntl(fd,F_GETFL);
int new_option=old_option|O_NONBLOCK;
fcntl(fd,F_SETFL,new_option);
return new_option;
}
typedef struct fd_info_s
{
int fd;
int type;/*-1,非法 0:server 1:client*/
}fd_info_t;
//数组大小可根据需要扩充
fd_info_t g_fds[512];
int main(int argc,char *argv[])
{
struct sockaddr_in addr;
int epollfd;
struct epoll_event event1;
int fd;
int ret;
/*创建epollfd*/
epollfd=epoll_create(20);
/*添加第一个fd,用于accept*/
fd=socket(AF_INET,SOCK_STREAM,0);
if(fd<0)
{
dprintf(STDERR_FILENO,"socket error",14);
return -1;
}
//先要对协议地址进行清零
bzero(&addr,sizeof(addr));
//设置Ipv4或ipv6
addr.sin_family=AF_INET;
//绑定本地端口号
addr.sin_port=htons(atoi(argv[1]));
//任何一个 IP 地址,让内核自行选择
addr.sin_addr.s_addr=INADDR_ANY;
//绑定套接口到本地协议地址
bind(fd,(struct sockaddr *)&addr,sizeof(addr));
//服务器开始监听
listen(fd,32767);
gSetNonblocking(fd);
//填充fd对应的结构体
g_fds[fd].fd=fd;
g_fds[fd].type=0;
event1.data.ptr=&g_fds[fd];
event1.events=EPOLLIN|EPOLLRDHUP;
ret=epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event1);
if(ret!=0)
{
if(errno==EEXIST)
{
epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&event1);
}
}
//printf("epollctl1\n");
while(1)
{
int number;
int i;
struct epoll_event ep_events[512];
fd_info_t *pfdinfo;
//监听最大512个事件
number=epoll_wait(epollfd,ep_events,512,-1);
if(number < 0 && errno !=EINTR)
{
printf("epoll failure\n");
break;
}
//printf("num=%d\n",number);
for(i=0;itype == 0 && (ep_events[i].events & EPOLLIN))
{
struct sockaddr_in cliaddr;
socklen_t clilen =sizeof(struct sockaddr_in);
fd=accept(pfdinfo->fd,(struct sockaddr *)&cliaddr,&clilen);
printf("\n accept fd: %d\n",fd);
g_fds[fd].fd=fd;
g_fds[fd].type=1;
event1.data.ptr=&g_fds[fd];
event1.events=EPOLLIN|EPOLLRDHUP;
ret=epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event1);
if(ret!=0)
{
//如果事件已经添加过,则更改其状态
if(errno==EEXIST)
{
epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&event1);
}
}
}
if(pfdinfo->type == 1 && (ep_events[i].events & EPOLLIN))
{
char text[512];
int ret=recv(pfdinfo->fd,text,512,0);
if(ret>0)
{
text[ret]='\0';
//printf("Recv(%d):%s\n",ret,text);
printf("request fd:%d\n",pfdinfo->fd);
g_fds[pfdinfo->fd].fd=pfdinfo->fd;
g_fds[pfdinfo->fd].type=1;
event1.data.ptr=&g_fds[pfdinfo->fd];
event1.events=EPOLLIN|EPOLLRDHUP|EPOLLOUT;;
ret=epoll_ctl(epollfd,EPOLL_CTL_MOD,pfdinfo->fd,&event1);
}
else if(ret==0)
{
event1.events=0;
//删除事件
ret=epoll_ctl(epollfd,EPOLL_CTL_MOD,pfdinfo->fd,&event1);
printf("ret=%d\n",ret);
perror("");
close(pfdinfo->fd);
printf("\n close fd: %d\n",pfdinfo->fd);
g_fds[pfdinfo->fd].fd=-1;
break;
}
else if(errno == EWOULDBLOCK)
{
printf("wouldblock\n");
break;
}
else if(errno == EPIPE)
{
printf("Broken pipe\n");
break;
}
}
if(pfdinfo->type == 1 && (ep_events[i].events & EPOLLOUT))
{
int n;
char text[512];
sprintf(text,"%s","this is epoll server say hello\n");
n=strlen(text);
write(pfdinfo->fd,text,n);
printf("reply fd:%d\n",pfdinfo->fd);
event1.events=EPOLLIN|EPOLLRDHUP;
ret=epoll_ctl(epollfd,EPOLL_CTL_MOD,pfdinfo->fd,&event1);
}
}
}
}
client端:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define path "tempfile.socket"
int sock;
int epollfd;
void sig(int sig)
{
char buf[512];
memset(buf, 0, sizeof(buf));
sprintf(buf, "close client %d",sock);
write(sock, buf, strlen(buf));
close(epollfd);
close(sock);
}
void gCtrlfd(int epollfd,int fd,struct epoll_event event)
{
int ret;
ret=epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&event);
if(ret!=0)
{
if(errno==EEXIST)
{
epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&event);
}
}
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Usage:./exec [port]\n");
exit(-1);
}
signal(SIGINT, sig);
sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[1]));
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sock, (struct sockaddr *)&addr, sizeof(addr));
int old = fcntl(sock, F_GETFL);
int newoption = old | O_NONBLOCK;
fcntl(sock, F_SETFL, newoption);
char buf[512];
memset(buf, 0, sizeof(buf));
/*创建epoll fd*/
epollfd = epoll_create(5);
struct epoll_event event[128];
struct epoll_event e1,e2,e3;
/*将e1 e2 初始化*/
e1.data.fd = sock;
e1.events = EPOLLIN;
gCtrlfd(epollfd,sock,e1);
e2.data.fd = STDIN_FILENO;
e2.events = EPOLLIN;
gCtrlfd(epollfd,STDIN_FILENO,e2);
int nR;
int ret;
int i;
while (1)
{
int number = epoll_wait(epollfd, event, 128, -1);
if (number <= 0)
{
printf("epoll_wait error\n");
return 0;
}
// printf("num=%d\n",number);
for(i = 0; i < number; ++i)
{
if (event[i].data.fd == sock)
{
if(event[i].events & EPOLLIN)
{
if(event[i].data.fd == sock)
{
memset(buf, 0, sizeof(buf));
nR = read(sock, buf, 512);
if (nR == 0)
{
close(sock);
break;
}
printf("%s\n",buf);
e1.data.fd = sock;
e1.events = e1.events | EPOLLOUT;
gCtrlfd(epollfd,sock,e1);
}
}
if(event[i].events & EPOLLOUT)
{
memset(buf, 0, sizeof(buf));
printf("aaaa\n");
sprintf(buf,"%s","this is client: say hello\n");
nR=sizeof(buf);
write(sock, buf, nR);
e1.data.fd = sock;
e1.events = e1.events& ~EPOLLOUT;
gCtrlfd(epollfd,sock,e1);
}
}
else if ( event[i].data.fd == STDIN_FILENO && (event[i].events & EPOLLIN))
{
printf("please input string:");
fflush(stdout);
memset(buf, 0, sizeof(buf));
nR = read(STDIN_FILENO, buf, 512);
if (nR <= 0)
{
printf("errno[%d]:%s\n", errno, strerror(errno));
}
ret = write(sock, buf, nR);
if (ret == 0 && errno == EINTR)
{
printf("write sock error\n");
exit(-1);
}
else if (ret < 0)
{
printf("write sock ret < 0\n");
exit(-1);
}
printf("Send [%d]byte\n", ret);
}
}
}
close(sock);
return 0;
}