#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <poll.h>
#include <unistd.h>
#include <sys/types.h>
#define ipaddress "127.0.0.1"
#define port 8787
#define maxline 1024
#define listenq 5
#define open_max 1000
#define inftim -1
//函数声明
//创建套接字并进行绑定
static int socket_bind(const char* ip,int port);
//io多路复用poll
static void do_poll(int listenfd);
//处理多个连接
static void handle_connection(struct pollfd *connfds,int num);
int main(int argc,char *argv[])
{
int listenfd,connfd,sockfd;
struct sockaddr_in cliaddr;
socklen_t cliaddrlen;
listenfd = socket_bind(ipaddress,port);
listen(listenfd,listenq);
do_poll(listenfd);
return 0;
}
static int socket_bind(const char* ip,int port)
{
int listenfd;
struct sockaddr_in servaddr;
listenfd = socket(af_inet,sock_stream,0);
if (listenfd == -1)
{
perror("socket error:");
exit(1);
}
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = af_inet;
inet_pton(af_inet,ip,&servaddr.sin_addr);
servaddr.sin_port = htons(port);
if (bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1)
{
perror("bind error: ");
exit(1);
}
return listenfd;
}
static void do_poll(int listenfd)
{
int connfd,sockfd;
struct sockaddr_in cliaddr;
socklen_t cliaddrlen;
struct pollfd clientfds[open_max];
int maxi;
int i;
int nready;
//添加监听描述符
clientfds[0].fd = listenfd;
clientfds[0].events = pollin;
//初始化客户连接描述符
for (i = 1;i < open_max;i++)
clientfds.fd = -1;
maxi = 0;
//循环处理
for ( ; ; )
{
//获取可用描述符的个数
nready = poll(clientfds,maxi+1,inftim);
if (nready == -1)
{
perror("poll error:");
exit(1);
}
//测试监听描述符是否准备好
if (clientfds[0].revents & pollin)
{
cliaddrlen = sizeof(cliaddr);
//接受新的连接
if ((connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&cliaddrlen)) == -1)
{
if (errno == eintr)
continue;
else
{
perror("accept error:");
exit(1);
}
}
fprintf(stdout,"accept a new client: %s:%d\n", inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);
//将新的连接描述符添加到数组中
for (i = 1;i < open_max;i++)
{
if (clientfds.fd < 0)
{
clientfds.fd = connfd;
break;
}
}
if (i == open_max)
{
fprintf(stderr,"too many clients.\n");
exit(1);
}
//将新的描述符添加到读描述符集合中
clientfds.events = pollin;
//记录客户连接套接字的个数
maxi = (i > maxi ? i : maxi);
if (--nready <= 0)
continue;
}
//处理客户连接
handle_connection(clientfds,maxi);
}
}
static void handle_connection(struct pollfd *connfds,int num)
{
int i,n;
char buf[maxline];
memset(buf,0,maxline);
for (i = 1;i <= num;i++)
{
if (connfds.fd < 0)
continue;
//测试客户描述符是否准备好
if (connfds.revents & pollin)
{
//接收客户端发送的信息
n = read(connfds.fd,buf,maxline);
if (n == 0)
{
close(connfds.fd);
connfds.fd = -1;
continue;
}
// printf("read msg is: ");
write(stdout_fileno,buf,n);
//向客户端发送buf
write(connfds.fd,buf,n);
}
}
}