int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
管理多个IO事件;
int nfds :要管理的事件最大值+1;
fd_set *readfds: 关注可读事件,和connect 事件
fd_set *writefds:关注可写事件
fd_set *exceptfds:关注异常事件
struct timeval *timeout:设定超时时间,如果设置为NULL,则一直等待有事件到来,如果不为NULL则等待设定时间
void FD_CLR(int fd, fd_set *set); 将文件描述符从集合中移除
int FD_ISSET(int fd, fd_set *set); 判断文件描述符是否在这个集合中设置
void FD_SET(int fd, fd_set *set); 将文件描述符添加到集合中
void FD_ZERO(fd_set *set); 清空文件描述符
详细请参考:点击打开链接
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string>
#include <memory.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/time.h>
#include <errno.h>
#define BUFFSIZE 1024
#define PORT 5588
using namespace std;
template<typename T>
void log(T msg)
{
cout<<msg<<endl;
}
int initSock()
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sockaddr_t;
memset(&sockaddr_t, 0, sizeof(sockaddr_t));
sockaddr_t.sin_family = AF_INET;
sockaddr_t.sin_port = htons(PORT);
sockaddr_t.sin_addr.s_addr = htonl(INADDR_ANY);
/*设置为非阻塞*/
// int flags = fcntl(fd, F_GETFL, 0);
// fcntl(fd, F_SETFL, flags|O_NONBLOCK);
//设置地址重复利用
int on = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
{
log("setsockopt");
}
if (bind(fd, (struct sockaddr*)&sockaddr_t, sizeof(sockaddr_t)) < 0 )
{
log("bind is failed");
return -1;
}
if(listen(fd, SOMAXCONN) < 0)
{
log("listen is failed");
return -1;
}
return fd;
}
int acceptPool(int fd)
{
int acceptfd;
struct sockaddr_in clientAddr;
socklen_t len = sizeof(clientAddr);
fd_set rset;
fd_set allset;
FD_ZERO(&rset);
FD_ZERO(&allset);
FD_SET(fd, &allset);
int clientfds[FD_SETSIZE];
memset(clientfds, -1, sizeof(clientfds));
int retval = 0;
int MAX = fd;
char readbuff[1024];
int i = 0;
while(true)
{
rset = allset;
retval = select(MAX + 1, &rset, NULL, NULL, NULL);
if (retval < 0)
{
if (retval == EINTR)
{
log("select error is EINTR");
continue;
}
else
{
return -1;
}
}
else if(retval == 0)
{
continue;
}
else
{
if (FD_ISSET(fd, &rset))//查看是否为connect 事件
{
acceptfd = accept(fd,(struct sockaddr*)&clientAddr, &len);
if (acceptfd < 0 )
{
continue;
}
for (i = 0; i < FD_SETSIZE; ++i)
{
if (clientfds[i] < 0)
{
clientfds[i] = acceptfd;
break;
}
}
if (i == FD_SETSIZE)
{
log("too many clients ");
exit(0);
}
if (MAX < acceptfd)
{
MAX = acceptfd;
}
FD_SET(acceptfd, &allset);
if (--retval <= 0)
{
continue;
}
}
for (int i = 0; i < FD_SETSIZE; ++i)
{
if (clientfds[i] < 0)
{
continue;
}
acceptfd = clientfds[i];
if (FD_ISSET(acceptfd, &rset))
{
memset(readbuff, 0, sizeof(readbuff));
int n = read(acceptfd, readbuff, sizeof(readbuff));
if (n < 0)
{
log("read error");
exit(0);
}
else if (n == 0)
{
log("client is close");
close(acceptfd);
clientfds[i] = -1;
FD_CLR(acceptfd, &allset);
continue;
}
log(readbuff);
write(acceptfd, readbuff, strlen(readbuff));
if (--retval <= 0)
{
break;
}
}
}
}
// pthread_t thread;
// pthread_create(&thread, NULL, pool, (void*)&acceptfd);
}
return 0;
}
int main(int argc, char const *argv[])
{
int fd = initSock();
acceptPool(fd);
return 0;
}