//util.h
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/time.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/epoll.h>
#define backlogs 10
#define BUF_SIZE 150
int Socket(int domain,int type,int protocol)
{
int fd=socket(domain,type,protocol);
if(fd==-1)
return -1;
return fd;
}
int Bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
{
int ret=bind(sockfd,addr,addrlen);
if(ret==-1)
return -1;
return ret;
}
int Listen(int sockfd,int backlog)
{
int ret=listen(sockfd,backlog);
if(ret==-1)
return -1;
return ret;
}
int start_up(const char* ip,int port)
{
int fd=Socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in ser_addr;
ser_addr.sin_family=AF_INET;
ser_addr.sin_port=htons(port);
ser_addr.sin_addr.s_addr=inet_addr(ip);
int on=1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int));
socklen_t addrlen=sizeof(struct sockaddr);
Bind(fd,(struct sockaddr*)&ser_addr,addrlen);
Listen(fd,backlogs);
return fd;
}
///
//ser.c
#include"util.h"
#define OPEN_MAX 5000
int main(int argc,char *argv[])
{
int i,listenfd,connfd,sockfd;
int n,num=0;
ssize_t nready,efd,res;
char buf[BUF_SIZE],str[INET_ADDRSTRLEN];//16
socklen_t clilen;
struct sockaddr_in cliaddr,servaddr;
struct epoll_event tep,ep[OPEN_MAX];//tep:epoll_ctl参数 ep: epoll_wait()参数
listenfd=start_up(argv[1],atoi(argv[2]));
efd=epoll_create(OPEN_MAX); //创建epoll模型,efd指向红黑树根节点
if(efd==-1)
{
perror("epoll_create error!\n");
exit(1);
}
tep.events=EPOLLIN; tep.data.fd=listenfd; //指定listenfd的监听事件为"读"
res=epoll_ctl(efd,EPOLL_CTL_ADD,listenfd,&tep);//将listenfd及对应的结构体设置到树上,
//efd可找到该树
if(res==-1)
{
perror("epoll_ctl error!\n");
exit(1);
}
while(1)
{
//epoll为server阻塞监听事件,ep为struct epoll_event类型数组,OPEN_MAX为数组容量,-1表示永
//久阻塞
nready=epoll_wait(efd,ep,OPEN_MAX,-1);
if(nready==-1)
{
perror("epoll_wait error!!!\n");
exit(1);
}
for(i=0;i<nready;i++)
{
if(!(ep[i].events & EPOLLIN))
continue;
if(ep[i].data.fd==listenfd)
{
clilen=sizeof(struct sockaddr);
connfd=accept(listenfd,(struct sockaddr*)&cliaddr,&clilen);
printf("Received from %s at PORT %d\n",
inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
printf("cfd %d------client %d\n",connfd,++num);
tep.events=EPOLLIN; tep.data.fd=connfd;
res=epoll_ctl(efd,EPOLL_CTL_ADD,connfd,&tep);
if(res==-1)
{
perror("epoll_ctl error!\n");
exit(1);
}
}
else //不是listenfd 而是接发数据
{
sockfd=ep[i].data.fd;
n=recv(sockfd,buf,strlen(buf)+1,0);
if(n==0) //说明客户端关闭连接
{
res=epoll_ctl(efd,EPOLL_CTL_DEL,sockfd,NULL);//将该文件描述符从红黑树中摘除
/* if(res==-1)
{
perror("epoll_ctl error!!!\n");
exit(1);
}*/
close(sockfd); //关闭与客户端的连接
printf("client[%d] closed connection!!!\n",sockfd);
}
else if(n<0)//出错
{
perror("read n<0 error!!!\n");
res=epoll_ctl(efd,EPOLL_CTL_DEL,sockfd,NULL);
close(sockfd);
}
else
{
for(i=0;i<n;i++)
buf[i]=toupper(buf[i]);
send(sockfd,buf,n,0);
}
}
}
}
close(listenfd);
close(efd);
return 0;
}
///
//cli.c
#include"util.h"
int main(int argc,char *argv[])
{
char sendbuf[128];
char recvbuf[128];
socklen_t addrlen=sizeof(struct sockaddr);
int cli_fd=socket(AF_INET,SOCK_STREAM,0);
if(cli_fd==-1)
return -1;
struct sockaddr_in seraddr;
seraddr.sin_family=AF_INET;
seraddr.sin_port=htons(atoi(argv[2]));
seraddr.sin_addr.s_addr=inet_addr(argv[1]);
int ret=connect(cli_fd,(struct sockaddr*)&seraddr,addrlen);
if(ret==-1)
{
perror("connect error!\n");
return -1;
}
else
printf("success\n");
while(1)
{
printf("Cli:>");
scanf("%s",sendbuf);
send(cli_fd,sendbuf,strlen(sendbuf)+1,0);
recv(cli_fd,recvbuf,128,0);
printf("From Self Cli:%s\n",recvbuf);
}
close(cli_fd);
return 0;
}
linux c IO复用之epoll模型实例 实现服务器与多个客户端进行通信
最新推荐文章于 2024-05-29 18:41:36 发布