/*
* poll_socket.c
* This program demonstrates how to use the poll function.
* Note that although we did not cover sockets in this book,
* the code will remain the same for file descriptors. To use
* this program, open several xterms, run the program, and then
* telnet to any of the ports. Once the telnet session is connected
* type anything and it will echo back. For example:
*
* From xterm 1:
*
* bash$ ./poll_socket
*
* From xterm 2:
*
* bash$ telnet localhost 8888
*
* From xterm 3:
*
* bash$ telnet localhost 8889
*
* to compile: gcc -O -pipe poll_socket.c -o poll_socket
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <poll.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>
/* our defines */
#define PORT (8888)
#define MAXBUFF (1024)
#define MAX_CONN (16)
#define TIMEOUT (1024 * 1024)
#define MY_MAX(a,b) (a = (a > b) ? a : b )
#define POLL_ERR (-1)
#define POLL_EXPIRE (0)
int main(int argc, char **argv)
{
int i, j, max = 0, sfds[MAX_CONN], afd;
size_t len;
fd_set list;
char buff[MAXBUFF];
struct sockaddr_in sock[MAX_CONN];
struct pollfd pfds[MAX_CONN];
/* initialize our buffer */
memset(buff, 0, MAXBUFF);
/*
* We will loop through each file descriptor. First,
* we will create a socket bind to it and then call
* listen. If we get and error we simply exit,
* which is fine for demo code, but not good in the
* real world where errors should be handled properly.
*/
for( i = 0; i < MAX_CONN; i++ )
{
/* check to see that we can create them */
if( (sfds[i] = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
perror("Cannot create socket");
exit(1);
}
/* now fill out the socket stuctures */
memset(&sock[i], 0, sizeof(struct sockaddr_in));
sock[i].sin_family = AF_INET;
sock[i].sin_port = htons(PORT + i);
len = INADDR_ANY;
memset(&sock[i].sin_addr, len, sizeof(struct in_addr));
/* Now bind to the socket */
if( bind(sfds[i], (struct sockaddr *) &sock[i], sizeof(struct sockaddr_in)) < 0 )
{
perror("Cannot bind to the socket");
exit(1);
}
/* set our options */
if( setsockopt(sfds[i], SOL_SOCKET, SO_REUSEADDR, &j, sizeof(int)) < 0 )
{
perror("Cannot set socket options \n");
}
/* set the socket to the listen state */
if( listen(sfds[i], 5) < 0 )
{
perror("Failed to listen on the socket \n");
}
/* now set our pollfd struct */
pfds[i].fd = sfds[i];
pfds[i].events = POLLIN ;
}/* for */
/*
* Our main loop. Note, with the poll function we do
* not need to modify our structure before we call
* poll again. Also note that the overall function
* is much easier to implement over select.
*/
while( 1 )
{
/*
* Now call poll. When poll returns, one of
* the three conditions will be true:
* I) The timeout has expired
* II) The poll call had an error
* III) We have a socket ready to accept
*/
j = poll(pfds, (unsigned int)MAX_CONN, TIMEOUT);
switch( j )
{
case POLL_EXPIRE:
printf("Timeout has expired !\n");
break;
case POLL_ERR:
perror("Error on poll");
default:
/*
* Now we have to loop through each descriptor to
* see which is ready to accept. We will know if
* the POLLIN bit is set on this descriptor that this
* descriptor is ready to use.
*/
for( i =0; i < MAX_CONN; i++ )
{
if( pfds[i].revents & POLLIN )
{
/*
* We now have to accept the connection and then
* echo back what is written.
*/
printf("We have a connection \n");
len = sizeof(struct sockaddr_in);
afd = accept(sfds[i], (struct sockaddr *)&sock[i], &len);
len = read(afd, buff, MAXBUFF);
write(afd, buff, len +1);
printf("Echoing back:\n %s \n");
close(afd);
}
} /* for */
} /* switch */
}/* while(1) */
/* FIN */
return(0);
} /* main */
syntax highlighted by Code2HTML, v. 0.9