select模型
//selectServer.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/select.h>
#include <errno.h>
#include <vector>
int InitServer(const unsigned int port);
int main(int argc,char** argv)
{
int listenfd=InitServer(atoi(argv[1]));
if(listenfd==-1)
{
printf("InitServer failed..\n");
return -1;
}
std::vector<int> clientfds;
fd_set readfdset;
FD_ZERO(&readfdset);
FD_SET(listenfd,&readfdset);
int maxfd;
maxfd=listenfd;
struct timeval sttime;
sttime.tv_sec=30;
while(true)
{
fd_set readfdsetTmp=readfdset;
int infds=select(maxfd+1,&readfdsetTmp,NULL,NULL,NULL);
if(infds<0)
{
printf("select error..\n");
perror("select failed: ");
break;
}
else if(infds==0)
{
printf("timeout..\n");
continue;
}
else
{
for(int eventfd=0;eventfd<=maxfd;eventfd++)
{
if(FD_ISSET(eventfd,&readfdsetTmp)<=0)
continue;
if(eventfd==listenfd)
{
//发生listen事件,有client连接
struct sockaddr_in client_addr;
socklen_t client_addr_size=sizeof(client_addr);
int clientfd = accept(listenfd, (struct sockaddr*)&client_addr,(socklen_t*)&client_addr_size);
printf("client(%d) connectd..\n",clientfd);
FD_SET(clientfd,&readfdset);
//添加描述符,更新maxfd
if(maxfd<clientfd)
maxfd=clientfd;
clientfds.push_back(clientfd);
continue;
}
else
{
//有数据可读事件,或对端断开事件
char buf[1024];
memset(buf,0,sizeof(buf));
size_t isize = recv(eventfd,buf,sizeof(buf),0); //clientfd是会变的,要传eventfd进recv和send
if(isize<0)
{
//断开连接
printf("client(%d) disconneted..\n",eventfd);
close(eventfd); //关闭连接
for(auto iter=clientfds.begin();iter!=clientfds.end();iter++)
{
if(*iter==eventfd)
clientfd.erase(iter);
}
FD_CLR(eventfd,&readfdset); //该bit位置0
if(eventfd==maxfd) //只有当移除的eventfd是maxfd时,才需要更新maxfd
{
for(int i=maxfd;i>=0;i--) //找到新的最大的还是1的eventfd
{
if(FD_ISSET(eventfd,&readfdset))
{
maxfd=eventfd;
break;
}
}
}
continue;
}
//接收数据
printf("recv(%d):%s,size=%d\n",eventfd,buf,isize) ;
send(eventfd,buf,strlen(buf),0);
}
}
}
}
return 0;
}
int InitServer(const unsigned int port)
{
int sockfd=-1;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1) return -1;
int opt=1;
unsigned int len=sizeof(opt);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, len);
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(port);
if(bind(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) == -1)
{
close(sockfd);
sockfd=-1;
return -1;
}
if(listen(sockfd, 5) == -1)
{
close(sockfd);
sockfd=-1;
return -1;
}
return sockfd;
}
//selectClient.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>
#include <sys/select.h>
#include <netdb.h>
bool ConnectServer(int* sockfd, const char* ip, int port);
int main(int argc,char** argv)
{
int serverfd=-1;
if(ConnectServer(&serverfd,"127.0.0.1",atoi(argv[1]))==false)
{
printf("connect failed..\n");
return -1;
}
printf("connected..\n");
char buf[1024];
while(true)
{
memset(buf,0,sizeof(buf));
printf("enter input:\n");
scanf("%s",buf);
if(send(serverfd,buf,strlen(buf),0)==false)
{
printf("send error..\n");
return -1;
}
printf("send:%s\n",buf);
memset(buf,0,sizeof(buf));
if(recv(serverfd,buf,sizeof(buf),0)==false)
{
printf("recv error..\n");
return -1;
}
printf("recv:%s\n",buf);
}
return 0;
}
bool ConnectServer(int* sockfd, const char* ip, int port)
{
struct sockaddr_in server_addr;
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=inet_addr(ip);
server_addr.sin_port=htons(port);
*sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(*sockfd==-1)
{
return false;
}
if(connect(*sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
{
close(*sockfd);
*sockfd=-1;
return false;
}
return true;
}
2.poll模型
//pollServer.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>
#include <vector>
#include <time.h>
#include <poll.h>
#include <fcntl.h>
#define MAXNFDS 1024
int InitServer(const unsigned int port);
int main(int argc,char** argv)
{
int listenfd=InitServer(atoi(argv[1]));
printf("listenfd=%d\n",listenfd);
if(listenfd==-1)
{
printf("InitServer failed..\n");
return -1;
}
//初始化数组
int maxfd;
struct pollfd fds[MAXNFDS];
for(int i=0;i<MAXNFDS;i++)
{
fds[i].fd=-1;
}
//添加listenfd到数组
fds[listenfd].fd=listenfd;
fds[listenfd].events=POLLIN; //监听读数据事件
fds[listenfd].revents=0;
maxfd=listenfd;
while(1)
{
int infds=poll(fds,maxfd+1,-1);
if(infds<0)
{
printf("poll error..\n");
perror("poll failed: ");
break;
}
//超时返回0
if(infds==0)
{
printf("timeout..\n");
continue;
}
//遍历数组
for(int eventfd=0;eventfd<=maxfd;eventfd++)
{
if(fds[eventfd].fd==-1) //-1表示不监视描述符
continue;
/*
if(!(fds[eventfd].revents&POLLIN)) //发生的不是POLLIN数据可读事件
continue;
fds[eventfd].revents=0; //revents置0
*/
//下面是数据可读事件
if((eventfd==listenfd) && (fds[eventfd].revents&POLLIN))
{
fds[eventfd].revents=0;
struct sockaddr_in client_addr;
socklen_t client_addr_size=sizeof(client_addr);
int clientfd = accept(listenfd, (struct sockaddr*)&client_addr,&client_addr_size);
if(clientfd<0)
printf("accept failed..\n");
printf("%ld client(%d) connectd..\n",time(0),clientfd);
//close client which is more than MAXNFDS
if(clientfd>MAXNFDS)
{
printf("clientfd(%d) > MAXNFDS(%d), close client..\n",clientfd,MAXNFDS);
close(clientfd);
continue;
}
//把clientfd添加监视
fds[clientfd].fd=clientfd;
fds[clientfd].events=POLLIN;
fds[clientfd].revents=0;
//更新maxfd
if(maxfd<clientfd)
maxfd=clientfd;
printf("maxfd=%d\n",maxfd);
continue;
}
else if(fds[eventfd].revents&POLLIN)
{
fds[eventfd].revents=0;
char buf[1024];
memset(buf,0,sizeof(buf));
size_t isize = recv(eventfd,buf,sizeof(buf),0);
if(isize<=0)
{
printf("%ld client(%d) disconneted..\n",time(0),eventfd);
close(eventfd);
//client断开,将clientfd移除监视
fds[eventfd].fd=-1;
if(eventfd==maxfd) //更新maxfd
{
for(int i=maxfd;i>0;i--)
{
if(fds[i].fd!=-1)
maxfd=i;
break;
}
printf("maxfd=%d\n",maxfd);
}
continue;
}
//printf("recv(%d):%s,size=%d\n",eventfd,buf,isize) ;
send(eventfd,buf,strlen(buf),0);
}
}
}
return 0;
}
int InitServer(const unsigned int port)
{
int sockfd=-1;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1) return -1;
int opt=1;
unsigned int len=sizeof(opt);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, len);
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(port);
if(bind(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) == -1)
{
close(sockfd);
sockfd=-1;
return -1;
}
if(listen(sockfd, 5) == -1)
{
close(sockfd);
sockfd=-1;
return -1;
}
return sockfd;
}
3.epoll模型
//epollServer.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>
#include <vector>
#include <time.h>
#include <sys/epoll.h>
#include <fcntl.h>
#define MAXEVENTS 100
int InitServer(const unsigned int port);
int main(int argc,char** argv)
{
int listenfd=InitServer(atoi(argv[1]));
printf("listenfd=%d\n",listenfd);
if(listenfd==-1)
{
printf("InitServer failed..\n");
return -1;
}
//创建epoll句柄
int epollfd=epoll_create(1);
if(epollfd<0) printf("epoll_create failed..\n");
//epoll_event封装listenfd和监视类型为有数据可读(EPOLLIN)
struct epoll_event ev;
ev.data.fd=listenfd;
ev.events=EPOLLIN;
epoll_ctl(epollfd,EPOLL_CTL_ADD,listenfd,&ev); //添加到epollfd
while(true)
{
struct epoll_event events[MAXEVENTS]; //epoll_wait返回时保存发生的事件
int infds=epoll_wait(epollfd,events,MAXEVENTS,-1);
if(infds<0)
{
printf("epoll_wait failed..\n");
break;
}
if(infds==0)
{
printf("timeout..\n");
break;
}
//发生的事件再events中从index=0依次保存
for(int i=0;i<infds;i++)
{
//listenfd上有数据可读事件发生
if((events[i].data.fd==listenfd) && (events[i].events&EPOLLIN))
{
struct sockaddr_in client_addr;
socklen_t client_addr_size=sizeof(client_addr);
int clientfd = accept(listenfd, (struct sockaddr*)&client_addr,&client_addr_size);
if(clientfd<0)
{
printf("accept failed..\n");
continue;
}
//连接上的客户端添加进监视
memset(&ev,0,sizeof(struct epoll_event)); //清空ev
ev.data.fd=clientfd;
ev.events=EPOLLIN;
epoll_ctl(epollfd,EPOLL_CTL_ADD,clientfd,&ev);
printf("%ld client(%d) connectd..\n",time(0),clientfd);
continue;
}
else if(events[i].events&EPOLLIN) //有数据可读事件
{
char buf[1024];
memset(buf,0,sizeof(buf));
size_t isize = recv(events[i].data.fd,buf,sizeof(buf),0);
if(isize<=0)
{
//把客户端fd从监视中删除
memset(&ev,0,sizeof(struct epoll_event));
ev.data.fd=events[i].data.fd;
ev.events=EPOLLIN;
epoll_ctl(epollfd,EPOLL_CTL_DEL,events[i].data.fd,&ev);
close(events[i].data.fd);
printf("%ld client(%d) disconneted..\n",time(0),events[i].data.fd);
continue;
}
printf("client(%d)recv msg:%s,size=%d\n",events[i].data.fd,buf,isize);
//send(events[i].data.fd,buf,strlen(buf),0);
//判断sockfd是否可写
fd_set tmpfd;
FD_ZERO(tmpfd);
FD_SET(events[i].data.fd,&tmpfd);
if(select(events[i].data.fd+1,0,&tmpfd,0,0)<0)
{
printf("没有可写数据的fd\n");
return -1;
}
if(write(events[i].data.fd,buf,strlen(buf))<0)
{
printf("write failed..\n");
close(events[i].data.fd);
return -1;
}
}
}
}
return 0;
}
int InitServer(const unsigned int port)
{
int sockfd=-1;
sockfd = socket(PF_INET, SOCK_STREAM, 0);
if(sockfd == -1) return -1;
int opt=1;
unsigned int len=sizeof(opt);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, len);
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(port);
if(bind(sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) == -1)
{
close(sockfd);
sockfd=-1;
return -1;
}
if(listen(sockfd, 5) == -1)
{
close(sockfd);
sockfd=-1;
return -1;
}
return sockfd;
}
标签:return,addr,int,复用,server,IO,Linux,sockfd,include
From: https://www.cnblogs.com/wk2522466153/p/18303668