|
From: arnuld on 25 Jun 2008 01:23 Asa matter of personal choice I like poll() more than select(). I have created a server that handles multiple clients using poll() ( from section 6.11 of UnP volume 1 by W Stevens) and it works fine except 3 problems: 1.) It gives compile-time error on using POLLRDNORM saying "POLLRDNORM" is not declared but when I use POLLIN it compiles fine. WHy I can't use POLLRDNORM ? 2.) Even thought I have tried using #include <sys/stropts.h> as advised by Stevens buut I still get INFTIM undeclared error. 3.) OPEN_MAX is undeclared and you can not use sysconf with _SC_OPEN_MAX argument because one of the return values of sysconf is "indeterminate" as told by Stevens. If it is undeclared/indeterminate then what value I can use ? I have just temporarily solved the problem by setting OPEN_MAX to 10000 but this is an ugly hack :( ----------------- poll-server.c ------------------------------------- /* A server handeling multiple clients using poll() */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/stropts.h> #include <poll.h> #define SERVER_IP "127.0.0.1" enum { ARRSIZE = 101, BACKLOG = 100, OPEN_MAX = 10000, INFTIM = -1 }; int main( int argc, char** argv ) { int sockfd, accept_fd, myport; struct sockaddr_in servaddr, cliaddr; socklen_t clilen; char arrc[ARRSIZE]; int recv_err; /* preparations for poll() */ struct pollfd clients[OPEN_MAX]; int i, nready; int curr_index, max_index; /* clear the array and the address structures */ memset( arrc, '\0', ARRSIZE ); memset( &servaddr, '\0', sizeof(servaddr) ); memset( &cliaddr, '\0', sizeof(cliaddr) ); if( argc != 2 ) { fprintf(stderr, "USAGE: ./file PORT\n"); exit( EXIT_FAILURE ); } else { myport = atoi( argv[1] ); } if( (sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) { perror("SOCKET() error\n"); exit( EXIT_FAILURE ); } servaddr.sin_family = AF_INET; servaddr.sin_port = htons(myport); if( inet_pton(AF_INET, SERVER_IP, &servaddr.sin_addr) <= 0 ) { perror("inet_pton: error\n"); exit(EXIT_FAILURE); } if( bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr)) < 0 ) { perror("BIND() error\n"); exit( EXIT_FAILURE ); } if( listen(sockfd, BACKLOG) < 0 ) { perror("LISTEN() error\n"); exit( EXIT_FAILURE ); } /* poll() initialisation */ clients[0].fd = sockfd; clients[0].events = POLLIN; max_index = 0; for(i = 1; i < OPEN_MAX; ++i ) { clients[i].fd = -1; } /* here we start to accept connections */ for( ; ; ) { nready = poll( clients, max_index + 1, INFTIM ); if( clients[0].revents & POLLIN ) { clilen = sizeof( cliaddr ); accept_fd = accept(sockfd, (struct sockaddr*)&servaddr, &clilen); printf("ACCEPT()ed \n"); /* add the new FD to the poll() */ for( i=1; i < OPEN_MAX; ++i ) { if( clients[i].fd < 0 ) { clients[i].fd = accept_fd; break; } } curr_index = i; /* check if the poll() is full of connections */ if( curr_index == OPEN_MAX ) { perror("Too many connections\n"); exit( EXIT_FAILURE ); } /* After the check, now we can add to events */ clients[curr_index].events = POLLIN; if( curr_index > max_index ) { max_index = curr_index; } if( --nready <= 0 ) { continue; } } /* if condition for checking connection is done with */ /* now we check & read the data */ for( i = 1; i <= max_index; ++i ) { if( clients[i].fd < 0 ) { continue; } if( clients[i].revents & (POLLIN | POLLERR) ) { if( (recv_err = recv(accept_fd, arrc, ARRSIZE, 0)) <= 0 ) { if( errno == ECONNRESET ) { perror("Remote-Clients did RESET the connection"); close( accept_fd ); clients[i].fd = -1; } else if( 0 == recv_err ) { perror("Remote-Clients closed the connection"); close( accept_fd ); clients[i].fd = -1; } else { perror("RECV() error"); exit( EXIT_FAILURE ); } } else { printf("RECV()ed Data\n"); if( send( accept_fd, arrc, ARRSIZE, 0 ) < 0 ) { perror("SEND() error"); exit( EXIT_FAILURE ); } } if( --nready <= 0 ) { break; } } } } return 0; } -- http://uttre.wordpress.com/ my email is @ the above address check "About Myself" page
From: David Schwartz on 25 Jun 2008 04:30 On Jun 24, 10:23 pm, arnuld <sunr...(a)invalid.address> wrote: > 1.) It gives compile-time error on using POLLRDNORM saying "POLLRDNORM" > is not declared but when I use POLLIN it compiles fine. WHy I can't use > POLLRDNORM ? You either don't have a platform that supports them or didn't request such report. Did you use the correct compiler flag to request XOPEN support? (Which might be '-D_XOPEN_SOURCE=600'.) > 2.) Even thought I have tried using #include <sys/stropts.h> as advised by > Stevens buut I still get INFTIM undeclared error. '-1' is documented to be an infinite wait. INFTIM is non-standard use and not considered good practice. See, for example: http://sourceware.org/bugzilla/show_bug.cgi?id=5982 > 3.) OPEN_MAX is undeclared and you can not use sysconf with _SC_OPEN_MAX > argument because one of the return values of sysconf is "indeterminate" as > told by Stevens. If it is undeclared/indeterminate then what value I can > use ? I have just temporarily solved the problem by setting OPEN_MAX to > 10000 but this is an ugly hack :( Why do you need to know this? You can use 'getdtablesize'. But a sane thing to do is determine the maximum socket value your program wishes to handle, possibly using sysconf(_SC_OPEN_MAX), possibly using 'getdtablesize', possibly reading your own config file, whatever, then use that. If you call 'open' or 'socket' and get a descriptor over your max, close it and treat that as an error (you are out of descriptors). DS
From: Rainer Weikusat on 25 Jun 2008 04:42 arnuld <sunrise(a)invalid.address> writes: > 1.) It gives compile-time error on using POLLRDNORM saying "POLLRDNORM" > is not declared but when I use POLLIN it compiles fine. WHy I can't use > POLLRDNORM ? Assuming this is on Linux: When compiling with _XOPEN_SOURCE defined, one also has the following, which convey no further information beyond the bits listed above: POLLRDNORM Equivalent to POLLIN. (poll(2)) > 2.) Even thought I have tried using #include <sys/stropts.h> as advised by > Stevens buut I still get INFTIM undeclared error. Have you considered taking a look at the header to determine if it defines the macro? (NB: It doesn't. Neither does any other header in my /usr/include). [...] > accept_fd = accept(sockfd, (struct sockaddr*)&servaddr, > &clilen); It is possible that the client closes the connection after poll reported that the listening descriptor is readable, but before the program executes an accept. Because this socket is in blocking mode, accept will then block until the next connection is available, preventing any I/O on other descriptors. > printf("ACCEPT()ed \n"); > /* add the new FD to the poll() */ > for( i=1; i < OPEN_MAX; ++i ) > { > if( clients[i].fd < 0 ) > { > clients[i].fd = accept_fd; > break; > } > } > [...] > /* now we check & read the data */ > for( i = 1; i <= max_index; ++i ) > { > if( clients[i].fd < 0 ) > { > continue; > } > > if( clients[i].revents & (POLLIN | POLLERR) ) > { > if( (recv_err = recv(accept_fd, arrc, ARRSIZE, 0)) <= 0 ) > { This should again be the descriptor associated with the current client (client[i].fd), not the one associated with the last accepted connection. [...] > else > { > printf("RECV()ed Data\n"); > if( send( accept_fd, arrc, ARRSIZE, 0 ) < 0 ) Same here.
From: arnuld on 25 Jun 2008 05:38 > On Wed, 25 Jun 2008 10:42:22 +0200, Rainer Weikusat wrote: > Assuming this is on Linux: sorry, I forgot to mention: UBUNTU fiesty [arnuld(a)sumit ~]$ gcc --version gcc (GCC) 4.1.2 (Ubuntu 4.1.2-0ubuntu4) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > When compiling with _XOPEN_SOURCE defined, one also has the > following, which convey no further information beyond the > bits listed above: > > POLLRDNORM > Equivalent to POLLIN. > (poll(2)) Well, my colleagues say that do not need to worry about POLLRDNORM. For our specific requirements we can use POLLIN and POLLOUT all the time. One more thing, this is from /usr/include/sys/features.h #ifndef _FEATURES_H #define _FEATURES_H 1 /* These are defined by the user (or the compiler) to specify the desired environment: __STRICT_ANSI__ ISO Standard C. _ISOC99_SOURCE Extensions to ISO C89 from ISO C99. _POSIX_SOURCE IEEE Std 1003.1. _POSIX_C_SOURCE If ==1, like _POSIX_SOURCE; if >=2 add IEEE Std 1003.2; if >=199309L, add IEEE Std 1003.1b-1993; if >=199506L, add IEEE Std 1003.1c-1995; if >=200112L, all of IEEE 1003.1-2004 _XOPEN_SOURCE Includes POSIX and XPG things. Set to 500 if Single Unix conformance is wanted, to 600 for the upcoming sixth revision. _XOPEN_SOURCE_EXTENDED XPG things and X/Open Unix extensions. _LARGEFILE_SOURCE Some more functions for correct standard I/O. _LARGEFILE64_SOURCE Additional functionality from LFS for large fi > Have you considered taking a look at the header to determine if it > defines the macro? (NB: It doesn't. Neither does any other header in my > /usr/include). yes, it is not defined there but defined elsewhere: [arnuld(a)sumit asm-x86_64]$ cat poll.h #ifndef __x86_64_POLL_H #define __x86_64_POLL_H /* These are specified by iBCS2 */ #define POLLIN 0x0001 #define POLLPRI 0x0002 #define POLLOUT 0x0004 #define POLLERR 0x0008 #define POLLHUP 0x0010 #define POLLNVAL 0x0020 /* The rest seem to be more-or-less nonstandard. Check them! */ #define POLLRDNORM 0x0040 #define POLLRDBAND 0x0080 #define POLLWRNORM 0x0100 #define POLLWRBAND 0x0200 #define POLLMSG 0x0400 #define POLLREMOVE 0x1000 #define POLLRDHUP 0x2000 struct pollfd { int fd; short events; short revents; }; #endif [arnuld(a)sumit asm-x86_64]$ pwd /usr/include/asm-x86_64 > It is possible that the client closes the connection after poll reported > that the listening descriptor is readable, but before the program > executes an accept. Because this socket is in blocking mode, accept will > then block until the next connection is available, preventing any I/O on > other descriptors. Earlier, like I did for bind() and listen() I did check for the return value of -1 but since Stevens does not have any check here I removed it because I know he is intelligent than me. -- http://lispmachine.wordpress.com/ my email is @ the above address check "About Myself" page
From: Geoff Clare on 25 Jun 2008 08:40 arnuld wrote: > 2.) Even thought I have tried using #include <sys/stropts.h> as advised by > Stevens buut I still get INFTIM undeclared error. If Stevens really did advise including <sys/stropts.h>, rather than <stropts.h>, he was wrong to do so. The standard header is <stropts.h>. (Not that this will make any difference to your problem, because - as others have pointed out - INFTIM is non-standard.) -- Geoff Clare <netnews(a)gclare.org.uk>
|
Next
|
Last
Pages: 1 2 3 4 5 Prev: A question about a readline() function Next: web server with pool of thread |