[comp.unix.wizards] HELP! BSD select

TAYBENGH%NUSDISCS.BITNET@cunyvm.cuny.edu (03/19/90)

        Recently I have a problem of using the select() system call in WIN/TCP
for VMS Release 3.2. According to the manuals provided by Wollongong, the
select() takes in NULL pointer for writefds/exceptfds, but I always encounter
access violation run-time error when I tried to call

        select(n, readfds, 0, 0, &timeout);

Moreover, select() supposed to block or return depend on the timeval (timeout)
passed in, but it always return immediately no matter what timeout value I
gives without setting any fle descriptors (channels). For example,

        timeout.tv_sec = 10000;
        FD_ZERO(&ready);
        FD_ZERO(&write);
        FD_ZERO(&except);
        FD_SET(sock, &ready);
        FD_SET(sock, &write);
        FD_SET(sock, &except);
        /*
         * Null pointer is not working, giving acess violation problems!
         */
        if (nfd = (select(sock+1, &ready, &write, &except, &timeout)) <0)
           perror("select");

        Anybody out there knows the solution, please help...
        Thanks.

-Beng Hang (taybengh@nusdiscs.bitnet)

zessel@tsetse.informatik.uni-kl.de (Holger Zessel) (03/20/90)

TAYBENGH%NUSDISCS.BITNET@cunyvm.cuny.edu writes:

 >select() takes in NULL pointer for writefds/exceptfds, but I always encounter
 >access violation run-time error when I tried to call

 >        select(n, readfds, 0, 0, &timeout);
You may have forgotten the & in front of readfds ?

 >Moreover, select() supposed to block or return depend on the timeval (timeout)
 >passed in, but it always return immediately no matter what timeout value I
 >gives without setting any fle descriptors (channels). For example,

 >        if (nfd = (select(sock+1, &ready, &write, &except, &timeout)) <0)
 >           perror("select");
Just take a very sharp look at the code and especially the parentheses.
 < has a higher priority than =
->
       if ((nfd = select(sock+1, &ready, &write, &except, &timeout)) <0)
          perror("select");

 >-Beng Hang (taybengh@nusdiscs.bitnet)
----------------------------------------------------------------
Holger Zessel, uucp: ...!uunet!unido!uklirb!incas!zessel
	or	zessel@informatik.uni-kl.de
	or	zessel%informatik.uni-kl.de@relay.cs.net (from usa)
Fachbereich Informatik, SFB124-D1
Universitaet Kaiserslautern, West-Germany

TAYBENGH%NUSDISCS.BITNET@cunyvm.cuny.edu (03/21/90)

Subject: Re: HELP! BSD select() on socket (WIN/TCP for VMS)

In arctle <9003211059.AA22332@portia.stanford.edu> Cuong Writes:
>>>gives without setting any fle descriptors (channels). For example,
>>
>>>        if (nfd = (select(sock+1, &ready, &write, &except, &timeout)) <0)
>>>           perror("select");
>>Just take a very sharp look at the code and especially the parentheses.
>> < has a higher priority than =
>>->
>>       if ((nfd = select(sock+1, &ready, &write, &except, &timeout)) <0)
>>          perror("select");
>
>Yes, but it doesn't help explain non-blocking behavior for
>Beng Hang.  What does this perror() report?  Bad access?
>If so, have you considered Holger's comment re. "&read" instead
>of "read"?  What is the actual code?
>
>Good luck,
>
>Cuong

        I admit the mistake made of assigning nfd. Thanks for the correction!
Below is the full source code (written in VAX-C).

In the message <9003202303.AA24028@uunet.uu.net> sent by Larry Jones:
>Since this is VMS, you might have more luck posting to a VMS news
>group like comp.os.vms rather than a unix group!

        I know I should post it somewhere else, but since there are a lot
of experts in this list, I push my luck. I apologize if I posted wrongly.

-Beng Hang Tay (email address: taybengh@nusdiscs.bitnet)
 Department of Information Systems and Computer Science
 National University of Singapore


----------------------cut here---------------------------------------------
/* Filename     : select_recv.c
   Author       : Beng Hang Tay (taybengh)
   Description  : Test program that receive buffers via stream service
                  using socket accept and recv. Note that raccept routine does
                  not distinguish the source, thus remote_sock is just a
                  memory space that store the incoming struct sockaddr_in value.
*/

#include <sys/types>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

main()
{
        int     sock, socklen, size, newsock, flag, nfd;
        struct  sockaddr_in     local_in, remote_in;
        char    inbuf[1024], outbuf[1024], hostname[15], str[10];
        u_short local_port, remote_port;
        fd_set  ready, write, except;
        struct  timeval to;

        printf("pls input the local port (>1000)\n");
        gets(str);
        local_port = atoi(str);
        printf("pls input the source hostname if any\n");
        gets(hostname);
        printf("pls input the source port if any, otherwise 0\n");
        gets(str);
        remote_port = atoi(str);
        printf("pls input the option if any, otherwise default=0\n");
        gets(str);
        flag = atoi(str);

        /* Create socket from which to read */
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock <0)
        {
            perror("opening stream socket");
            exit(1);
        }

        /* create sockaddr */
        local_in.sin_family = AF_INET;
        local_in.sin_addr.s_addr = INADDR_ANY;
        local_in.sin_port = htons(local_port);
        if (bind(sock, &local_in, sizeof(local_in)))
        {
            perror("binding stream socket");
            exit(1);
        }

        /* create sockaddr */
        printf("hostname =%s!\n", hostname);
        remote_in.sin_family = AF_INET;
/*      There is always a acess violation error due to the following
        statement, so it was masked off. The reason unknown!
        remote_in.sin_addr.s_addr = rhost(&hostname);
*/
        remote_in.sin_port = htons(remote_port);

#ifdef BDEBUG
        printf("\n\nbefore accept\n");
        printf("sock: \n");
        printf("family = %d \n", remote_in.sin_family);
        printf("sin_addr.s_addr = %x \n", ntohl(remote_in.sin_addr.s_addr));
        printf("net number = %x \n", inet_netof(remote_in.sin_addr));
        printf("local address part = %x \n", inet_lnaof(remote_in.sin_addr));
        printf("port # = %u\n", ntohs(remote_in.sin_port));
#endif

        listen(sock, 5);
        for (;;)
        {
           /*
            * set the poll time to very large value
            */
           to.tv_sec = 100000;
           to.tv_usec = 100000;
           FD_ZERO(&ready);
           FD_ZERO(&write);
           FD_ZERO(&except);
           FD_SET(sock, &ready);
           FD_SET(sock, &write);
           FD_SET(sock, &except);
           /* Null pointer is not working, giving acess violation problems! */
           if ((nfd = select(sock+1, &ready, &write, &except, 0)) <0)
           {
              perror("select");
              break;
           }

           /*
            * select() always return with nfd set to 1
            */
#ifdef  BDEBUG
        printf("select polling return nfd = %d\n", nfd);
        printf("timeval.tv_sec = %d, tv_usec = %d\n",
                to.tv_sec, to.tv_usec);
        printf("ready = %d, write =%d, except = %d\n",
                ready, write, except);
#endif

           /*
            * NEVER COME INSIDE THE IF
            */
           if (FD_ISSET(sock, &ready))
           {
              socklen = sizeof(remote_in);
              newsock = accept(sock, &remote_in, &socklen);

#ifdef BDEBUG
        printf("\nafter accept\n");
        printf("newsock = %d: \n", newsock);
        printf("family = %d \n", remote_in.sin_family);
        printf("sin_addr.s_addr = %x \n", ntohl(remote_in.sin_addr.s_addr));
        printf("net number = %x \n", inet_netof(remote_in.sin_addr));
        printf("local address part = %x \n", inet_lnaof(remote_in.sin_addr));
        printf("port # = %u\n", ntohs(remote_in.sin_port));
#endif
              if (newsock == -1)
                 perror("accept");
              else
                 for (;;)
                 {
                    /* receive message */
                    if ((size = recv(newsock, inbuf, 1024, flag)) < 0)
                        perror("receiving stream message");
                    if (size == 0)
                       printf("ending connection\n");
                    else
                       printf("received-->%s\n", inbuf);
                    if (inbuf[0] == '\n' || inbuf[0] == '\0')
                       exit(0);

                    /* send message */
                    printf("\nPls input the messages:\n");
                    gets(outbuf);
                    if ((size = send(newsock, outbuf,
                         sizeof(outbuf), flag)) < 0)
                       perror("send");
                    printf("buf sent-->%s, size =%d\n", outbuf, size);
                    if (outbuf[0] == '\n' || outbuf[0] == '\0')
                       exit(0);
                 }
           }
           close(newsock);
        }
}

-----------------cut here-----------------------------------------------------

TAYBENGH%NUSDISCS.BITNET@cunyvm.cuny.edu (03/21/90)

        I posted a old version source file in the previous posting. Below
are the latest source code and still has the same problem.
        I apologize for the mistake made. I am new to this list and I am
learning, please give me time to learn. Thanks!

-Beng Hang

--------------------------cut here----------------------------------
/* Filename     : select_recv.c
   Author       : Beng Hang Tay (taybengh)
   Description  : Test program that receive buffers via stream service
                  using socket accept and recv. Note that raccept routine does
                  not distinguish the source, thus remote_sock is just a
                  memory space that store the incoming struct sockaddr_in value.
*/

#include <sys/types>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

main()
{
        int     sock, socklen, size, newsock, flag, nfd;
        struct  sockaddr_in     local_in, remote_in;
        char    inbuf[1024], outbuf[1024], hostname[15], str[10];
        u_short local_port, remote_port;
        fd_set  ready, write, except;
        struct  timeval to;

        printf("pls input the local port (>1000)\n");
        gets(str);
        local_port = atoi(str);
        printf("pls input the source hostname if any\n");
        gets(hostname);
        printf("pls input the source port if any, otherwise 0\n");
        gets(str);
        remote_port = atoi(str);
        printf("pls input the option if any, otherwise default=0\n");
        gets(str);
        flag = atoi(str);

        /* Create socket from which to read */
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock <0)
        {
            perror("opening stream socket");
            exit(1);
        }

        /* create sockaddr */
        local_in.sin_family = AF_INET;
        local_in.sin_addr.s_addr = INADDR_ANY;
        local_in.sin_port = htons(local_port);
        if (bind(sock, &local_in, sizeof(local_in)))
        {
            perror("binding stream socket");
            exit(1);
        }

        /* create sockaddr */
        printf("hostname =%s!\n", hostname);
        remote_in.sin_family = AF_INET;
/*      There is always a acess violation error due to the following
        statement, so it was masked off. The reason unknown!
        remote_in.sin_addr.s_addr = rhost(&hostname);
*/
        remote_in.sin_port = htons(remote_port);

#ifdef BDEBUG
        printf("\n\nbefore accept\n");
        printf("sock: \n");
        printf("family = %d \n", remote_in.sin_family);
        printf("sin_addr.s_addr = %x \n", ntohl(remote_in.sin_addr.s_addr));
        printf("net number = %x \n", inet_netof(remote_in.sin_addr));
        printf("local address part = %x \n", inet_lnaof(remote_in.sin_addr));
        printf("port # = %u\n", ntohs(remote_in.sin_port));
#endif

        listen(sock, 5);
        for (;;)
        {
           /*
            * set the poll time to very large value
            */
           to.tv_sec = 100000;
           to.tv_usec = 100000;
           FD_ZERO(&ready);
           FD_ZERO(&write);
           FD_ZERO(&except);
           FD_SET(sock, &ready);
           FD_SET(sock, &write);
           FD_SET(sock, &except);
           /* Null pointer is not working, giving acess violation problems!
           if ((nfd = select(sock+1, &ready, 0, 0, &to)) <0) */
           if ((nfd = select(sock+1, &ready, &write, &except, &to)) <0)
           {
              perror("select");
              break;
           }

           /*
            * select() always return with nfd set to 1
            */
#ifdef  BDEBUG
        printf("select polling return nfd = %d\n", nfd);
        printf("timeval.tv_sec = %d, tv_usec = %d\n",
                to.tv_sec, to.tv_usec);
        printf("ready = %d, write =%d, except = %d\n",
                ready, write, except);
#endif

           /*
            * never come into the if-then
            */
           if (FD_ISSET(sock, &ready))
           {
              socklen = sizeof(remote_in);
              newsock = accept(sock, &remote_in, &socklen);

#ifdef BDEBUG
        printf("\nafter accept\n");
        printf("newsock = %d: \n", newsock);
        printf("family = %d \n", remote_in.sin_family);
        printf("sin_addr.s_addr = %x \n", ntohl(remote_in.sin_addr.s_addr));
        printf("net number = %x \n", inet_netof(remote_in.sin_addr));
        printf("local address part = %x \n", inet_lnaof(remote_in.sin_addr));
        printf("port # = %u\n", ntohs(remote_in.sin_port));
#endif
              if (newsock == -1)
                 perror("accept");
              else
                 for (;;)
                 {
                    /* receive message */
                    if ((size = recv(newsock, inbuf, 1024, flag)) < 0)
                        perror("receiving stream message");
                    if (size == 0)
                       printf("ending connection\n");
                    else
                       printf("received-->%s\n", inbuf);
                    if (inbuf[0] == '\n' || inbuf[0] == '\0')
                       exit(0);

                    /* send message */
                    printf("\nPls input the messages:\n");
                    gets(outbuf);
                    if ((size = send(newsock, outbuf,
                         sizeof(outbuf), flag)) < 0)
                       perror("send");
                    printf("buf sent-->%s, size =%d\n", outbuf, size);
                    if (outbuf[0] == '\n' || outbuf[0] == '\0')
                       exit(0);
                 }
           }
           close(newsock);
        }
}

zessel@tsetse.informatik.uni-kl.de (Holger Zessel) (03/22/90)

TAYBENGH%NUSDISCS.BITNET@cunyvm.cuny.edu writes:

....

 >/* Filename     : select_recv.c

In general I would say, the program is correct. At least on our suns (SunOs 4.03)
and Vaxen (Ultrix 2.2) it runs as expected:
	- stopping in select
After that I made a telnet <hostname> local_port to get an easy tcp connection..
	- Now the select comes back with one bit set in ready. Accept goes
	  ok and the recv gets some bytes I typed in telnet.
	  Every string I type in on demand is echo on the other side by telnet.

Seems everythink is ok.
But I have some annotations. There may be bug in your libs or os if selct does
not block.
 >#include <sys/types>
		    ^.h missing
....
 >           FD_ZERO(&ready);
 >           FD_ZERO(&write);
 >           FD_ZERO(&except);
 >           FD_SET(sock, &ready);
 >           FD_SET(sock, &write);
 >           FD_SET(sock, &except);
I think you don't need to set it in write as it is not your aim to write on the
accept socket. On our machines select blocks as sock is not connected and
one is not able to write or read on it. You should try it with throwing
out  FD_SET(sock, &write) and FD_SET(sock, &except). You don't need them.

 >           /* Null pointer is not working, giving acess violation problems!
 >           if ((nfd = select(sock+1, &ready, 0, 0, &to)) <0) */
The fact that this bombs is suspicious to me. I don't see a bug in the
expression. There may be a bug in select...
 >           if ((nfd = select(sock+1, &ready, &write, &except, &to)) <0)
 >           {
 >              perror("select");
 >              break;
 >           }

 >           /*
 >            * select() always return with nfd set to 1
 >            */
Mine did not, I don't know what's happening on your machine.

Hope that helps.

I do not e-mail this and poost it here as there may be people knowing
of a bug in select.
Holger
----------------------------------------------------------------
Holger Zessel, uucp: ...!uunet!unido!uklirb!incas!zessel
	or	zessel@informatik.uni-kl.de
	or	zessel%informatik.uni-kl.de@relay.cs.net (from usa)
Fachbereich Informatik, SFB124-D1
Universitaet Kaiserslautern, West-Germany