This poll() multiplexing I/O code is from UNP Chap 6 and I tested in my Ubuntu 18 Platform, and I tried to transfer data from a client which may cause the program to be blocked at the point of poll() function. In detail, we I connected a client to this server, "connect" will be printed, but when I want to send data from client, the code cannot display them but be blocked at the point of the poll() invocation. The sample output is :
Before poll()
After poll()
connect
Before poll()
Then blocked.
#define _GNU_SOURCE
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <errno.h>
#include <signal.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <poll.h>
#include <limits.h>
#include <sys/stropts.h>
#define MAXLINE 1024
#define OPENMAX 1024
#define BACKLOG 1024
#define SERV_PORT 8888
void errExit(char *arg)
{
printf("Err: %s\n", arg);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
int i, maxi, listenfd, connfd, sockfd;
int nready;
ssize_t n;
char buf[MAXLINE];
socklen_t clilen;
struct pollfd client[OPENMAX];
struct sockaddr_in cliaddr, servaddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd < 0)errExit("socket()");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
int opt = 1;
setsockopt(listenfd,SOL_SOCKET, SO_REUSEPORT, (const void*)&opt,sizeof(opt));
if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
errExit("bind()");
if(listen(listenfd,BACKLOG) == -1)
errExit("listen()");
client[0].fd = listenfd;
client[0].events = POLLRDNORM;
for(i = 1; i < OPENMAX; i ++ )
client[i].fd = -1;
maxi = 0;
while(1)
{
printf("Before poll()\n");
if( (nready = poll(client, maxi + 1, -1))==-1)
errExit("poll()");
printf("After poll()\n");
//**new connection**//
if(client[0].revents & POLLRDNORM)
{
clilen = sizeof(cliaddr);
if(connfd = accept(listenfd,(struct sockaddr*)&clilen, &clilen) == -1)
errExit("accept()");
printf("connect\n");
for( i = 1; i < OPENMAX ; i ++ )
{
if(client[i].fd < 0)
{
client[i].fd = connfd;
break;
}
}
if( i == OPENMAX)
errExit("TOO MANY CLIENTS");
client[i].events = POLLRDNORM;
if( i > maxi)
maxi = i;
if( --nready == 0) //no more readable descriotor
continue;
}
for( i = 1; i < maxi ; i ++)
{
if( (sockfd = client[i].fd) < 0)
continue;
if( client[i].revents & (POLLRDNORM | POLLERR))
{
if( (n = read(sockfd, buf, MAXLINE)) < 0)
{
if(errno == ECONNRESET)
{
printf("Connection Reset by Client\n");
close(sockfd);
client[i].fd = -1;
}
else
{
perror("Server: read error\n");
}
}
else if( n == 0)
{
client[i].fd = -1;
close(sockfd);
}
else
{
printf("%s\n",buf);
write(sockfd, buf, n);
}
if( -- nready <= 0 )
break;
}
}
}
}
Aucun commentaire:
Enregistrer un commentaire