poll_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <ctype.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <poll.h>
#include <errno.h>
#define MAXLINE 80
#define SERV_IP "127.0.0.1"
#define SERV_PORT 6666
#define OPEN_MAX 1024
void error_handing(const char *message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}
int main(int argc, char const *argv[])
{
int i,j,maxi,listenfd,connfd,sockfd;
int nready;
ssize_t n;
char buf[MAXLINE],str[INET_ADDRSTRLEN];
socklen_t clilen;
struct pollfd client[OPEN_MAX];
struct sockaddr_in cliaddr,servaddr;
listenfd = socket(PF_INET,SOCK_STREAM,0);
if(listenfd == -1)
error_handing("socket() error");
memset(&servaddr,0,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(SERV_IP);
servaddr.sin_port = htons(SERV_PORT);
if(bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1)
{
error_handing("bind() error");
}
if(listen(listenfd,128) == -1)
error_handing("listen() error");
client[0].fd = listenfd;
client[0].events = POLLRDNORM; //listenfd 监听普通读事件
for(i = 1; i < OPEN_MAX;i++)
{
client[i].fd = -1; //用-1初始化client[]里剩下元素
}
maxi = 0;
for(;;)
{
nready = poll(client,maxi+1,-1); //阻塞
if(client[0].revents & POLLRDNORM)
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd,(struct sockaddr*)&cliaddr,&clilen);
if (connfd == -1)
error_handing("accept() error");
printf("client ip:%s,port:%d\n",inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
for(i = 1;i<OPEN_MAX;i++)
{
if(client[i].fd < 0)
{
client[i].fd = connfd; //找到client[]中空闲的位置,存放accept返回的connfd
break;
}
}
if(i == OPEN_MAX)
error_handing("too many clients");
client[i].events = POLLRDNORM; //设置刚刚返回的connfd,监控读事件
if(i > maxi)
maxi = i; //更新client[]中最大元素下标
if(--nready <= 0)
continue; //没有更多就绪事件时,继续回到poll阻塞
}
for(i = 1;i<=maxi;i++) //检测client[]
{
if((sockfd = client[i].fd) < 0)
continue;
if(client[i].revents & (POLLRDNORM | POLLERR))
{
if((n = read(sockfd,buf,MAXLINE)) < 0)
{
if(errno == ECONNRESET) //当收到RST标志时
{
//connection reset by client
printf("client[%d] aborted connection\n",i );
close(sockfd);
client[i].fd = -1;
}else
{
error_handing("read() errno");
}
}else if( n == 0 )
{
//connection closed by client
printf("client[%d] closed connection\n",i );
close(sockfd);
client[i].fd = -1;
}else
{
for(j = 0;j < n;j++)
{
buf[j] = toupper(buf[j]);
}
write(sockfd,buf,n);
}
if(--nready <= 0)
break;
}
}
}
close(listenfd);
return 0;
}
poll_client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 1024
void error_handing(const char *message);
int main(int argc, char const *argv[])
{
char message[BUF_SIZE];
int str_len,recv_len,recv_cnt;
if (argc != 3)
{
printf("Usage : %s <IP> <port>\n",argv[0]);
exit(1);
}
int sock;
sock = socket(PF_INET,SOCK_STREAM,0);
if(sock == -1)
{
error_handing("socket() error");
}
struct sockaddr_in serv_adr;
memset(&serv_adr,0,sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = inet_addr(argv[1]);
serv_adr.sin_port = htons(atoi(argv[2]));
if(connect(sock,(struct sockaddr *)&serv_adr,sizeof(serv_adr)) == -1)
{
error_handing("connect() error");
}else
puts("Connected............");
while(1)
{
memset(&message,0,sizeof(message));
fputs("Input message(Q to quit): ",stdout);
fgets(message,BUF_SIZE,stdin);
if(!strcmp(message,"q\n") || !strcmp(message,"Q\n"))
break;
str_len = write(sock,message,strlen(message));
recv_len = 0;
while(recv_len < str_len)
{
recv_cnt = read(sock,&message[recv_len],BUF_SIZE - 1);
if(recv_cnt == -1)
{
error_handing("read() error");
}
recv_len += recv_cnt;
}
message[recv_len] = 0;
printf("Message from server: %s",message );
}
close(sock);
return 0;
}
void error_handing(const char *message)
{
fputs(message,stderr);
fputc('\n',stderr);
exit(1);
}