invalid argument in select() when peer socket is in FD_SET
Christoph P.U. Kukulies
kuku at kukulies.org
Mon Aug 1 15:09:52 UTC 2011
Am 31.07.2011 11:50, schrieb Christoph P.U. Kukulies:
> I have written a small to test TCP/IP roundtrip times of the packets
> in a proprietary protocol and while
> compiling and running this server on different platforms (Windows
> 7/cygwin, UbuntuLinux, FreeBSD 8.0 Release), I found
> that the server produces an error when the listening socket (on which
> the accpet() is performed) is member of the select()
> fd_set.
>
> On the other platforms the program works without error, just under
> FreeBSD I'm getting this "invalid argument" error.
>
> Comments appreciated (despite comments about the error checking logic :)
>
> Here is the code:
> // testsrv.c
> // gcc -o testsrv testsrv.c
> //
>
> #include <stdio.h>
> #include <unistd.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <arpa/inet.h>
> #include <netdb.h>
> #include <string.h>
>
> #include <sys/select.h>
>
> #define USEDBUFSIZ 60
> #define MAX_HOSTNAME 256
> #define MAXFDS 256
> #define CLRBUF memset(buf,0,sizeof(buf))
> #define max(a,b) (((a) > (b)) ? (a) : (b))
> static unsigned char buf[256];
> int array_of_fds[MAXFDS];
> static fd_set clientfds;
> #define SOCKET int
> void *memset(void *, int, size_t);
> int enter (int);
> int remov (int);
> int invalidip (char *);
> void exit (int);
> int getv (int, unsigned char *, int);
> int getfds ();
>
> int
> main(int argc, char **argv)
> {
> int nfds;
> static fd_set readfds;
> SOCKET ListenSocket, newsockfd;
> struct sockaddr_in cli_addr;
> struct sockaddr_in service;
> struct hostent *thisHost;
> int bOptVal = 0;
> int bOptLen = sizeof(int);
> char hostname[256];
> char *host_addr;
> struct in_addr addr = {0};
> char *ip;
> u_short port;
> int iResult = 0;
> int i , n, m, clilen, dummy, connect = 0;
> struct timeval tv;
> //---------------------------------------
> //Create a listening socket
> ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
> if (ListenSocket == -1) {
> perror("socket creation");
> return 1;
> } else
> printf("ListenSocket=%d\n", ListenSocket);
> //---------------------------------------
> //Bind the socket to the local IP address
> // and port 3210
> port = 3210;
> if (gethostname(hostname, 256))
> perror("gethostname failed\n"), exit(3);
> printf("%s\n", hostname), fflush(stdout);
> thisHost = gethostbyname(hostname);
> ip = inet_ntoa(*(struct in_addr *)(*thisHost->h_addr_list));
>
>
> if (argc == 2) {
> host_addr = argv[1];
> service.sin_addr.s_addr = inet_addr(host_addr);
> thisHost = gethostbyaddr((const char *)&service.sin_addr.s_addr,
> sizeof(service.sin_addr.s_addr),
> AF_INET);
> if (thisHost == 0)
> printf("host unknown\n"), exit(3);
> if (invalidip(host_addr))
> printf("invalid IP\n"), exit(4);
> } else {
> service.sin_addr.s_addr = inet_addr(ip);
> }
> service.sin_port = htons(port);
> service.sin_family = AF_INET;
>
> iResult = bind(ListenSocket, (struct sockaddr *)&service,
> sizeof(service));
> if (iResult == -1) {
> perror("bind");
> shutdown(ListenSocket, SHUT_RDWR);
> return 1;
> }
> listen(ListenSocket, SOMAXCONN);
> printf("SOMAXCONN=%d %d\n", SOMAXCONN, FD_SETSIZE);
> /* all sockets are put into an own array_of_fs */
> /* in the while() loop below the FD_SET id used by looping through
> the */
> /* array_of_fds to fill the readfds array in the select() */
>
> enter(ListenSocket);
>
> /*
> * Wait for connect
> */
> tv.tv_sec = 0;
> tv.tv_usec = 5000000; /* 5 seconds */
A friendly soul on FreeBSD-hackers told me that my
tv_usec value is wrong in the timeval struct above. FreeBSD checks if it
is in the range of
0<tv_usec<1000000 and not negative.
How I came to think that the socket could be the invaid parameter, I
don't know.
Maybe I did two changes to the code at once and was blaming the wrong one.
Thanks anyway for listening.
--
Christoph
More information about the freebsd-questions
mailing list