Solaris, sockets, and the select() statement.

Solaris, sockets, and the select() statement.

Post by Mark K. Cimi » Fri, 31 Mar 1995 04:00:00



I'm trying to use a select statement to notify my program when someone is
requesting a socket connection.  I can not get it to work.  I'm running
Solaris 2.4 and using gcc.  Below are the programs.  Can anyone help me
with this?

=======================================================================

#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <signal.h>
#include <sys/resource.h>
#include <sys/filio.h>
#include <setjmp.h>

int bindSocket(); /* Returns 0 on port in use,
                   * negative on network error,
                   * and positive on sucess. */

struct sockaddr_in server;
int sock;
int num_open;

struct connections {
  int s;
  int read;
  char *name;

} ;

struct connections array[10];

#define READ 1
#define WRITE 2
#define ERROR 4
void
main(int argc, char **argv)
{

  char buff[12];
  int i, j;
  fd_set soc, fd_set, fd_set_e;/*fd_set_r, fd_set_w */
  struct timeval time_val;
  struct rlimit rlp;
  int val, g, v, a, pid;
  int len;

  num_open = 0;
  memset(array, '\0', sizeof(struct connections) *10);

  if((sock = bindSocket(100)) <= 0)
    {
      perror("Error on connection");
      return ;
    }

  printf("Ready to read.\n");
  memset(buff, '\0', 12);
  time_val.tv_sec = 0;
  time_val.tv_usec = 0;

  (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &g, sizeof g);
  (void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &g, sizeof g);
  ioctl(sock, FIONBIO, (char *) &g);

  for(;;)
    {
      FD_ZERO(&fd_set);
      FD_ZERO(&fd_set_e);
      FD_ZERO(&soc);

      for(i = 0; i < num_open; i++)
        {
          FD_SET(array[i].s, &fd_set);
          FD_SET(array[i].s, &fd_set_e);
        }
      FD_SET(sock, &soc);

      getrlimit(RLIMIT_NOFILE, &rlp);
      printf("currentlimit = %d\tnum_open = %d\t i = %d\t", rlp.rlim_cur, num_open, i);
      fflush(stdout);
      val = v = 0;
      for(;;)
        {
          if(select(sock+1,
                    &soc,
                    NULL,
                    NULL,
                    &time_val) > 0 )
            {

              printf("New socket\n"); fflush(stdout);
              len = sizeof(server);
              if((array[num_open++].s = accept(sock, (struct sockaddr *)
                                               &server, &len)) <= 0)
                {
                  perror("accept error");
                  break;
                }
              break;
            }

          if(select(rlp.rlim_cur, &fd_set, NULL, NULL, &time_val) > 0 )
              val = READ;

/*        if(num_open && select(rlp.rlim_cur, NULL, &fd_set_w, NULL, &time_val) > 0 )
            val += WRITE;
*/
/*        if(num_open && select(rlp.rlim_cur, NULL, NULL, &fd_set_e, &time_val) > 0 )
            val += ERROR;
*/
          if(val > 0) break;
        }

      printf("val = %d\n", val);

      for(j = 0; j < num_open; j++)
        {
          if(FD_ISSET(array[j].s, &fd_set))
            {
              printf("Port read activity = %d\n", j);
              for (i = 0; i < 10; i++)
                {
                  if((g = recv(array[j].s, (void *)buff, 12, 0)) < 12)
                    {
                      printf("g = %d\n");
                      break;
                    }
                  printf("MESSAGE RECEIVED: %s\n", buff);
                }
              memset(buff, '\0', 12);
            }
          if(FD_ISSET(array[j].s, &fd_set_e))
            {
              printf("Port error activity = %d\n", j);
              close(array[j].s);
              num_open--;
            }
        }
    }
printf("HERE\n");  
  close(array[0].s);
  return;

}

int
bindSocket( int num )
{
  int on = 1;
  int len;
  int fd;
  int sock;

  server.sin_family = AF_INET;
  server.sin_addr.s_addr = INADDR_ANY;
  server.sin_port = htons(IPPORT_RESERVED + num);

  if((sock = socket(AF_INET, SOCK_STREAM, 0)) <= 0)
    {
       perror("socket error");
       return -1;
     }

  if(bind(sock, (struct sockaddr *) &server, sizeof(server)) < 0)
    {
       perror("bind error");
       return -1;
     }

  listen(sock, 10);
  return sock;

}

=====================================================================
/* Client program */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

int bindSocket( int, char* ); /* Returns 0 on connection reject,
                               * negative on network error, and positive
                               * on sucess.
                               */

void releaseSocket( int );

main( int argc, char **argv )
{
  char message[12];
  int i, s, j,a;
  struct linger l;

  if(argc != 2)
    {
      printf("Usage: %s hostname\n", argv[0]);
      return ;
    }

  if((s = bindSocket( 100, argv[1] )) <= 0)
    {
      perror("Error on socket connection");
      return ;
    }
  printf("Ready to send\n");
  for(j = 0; j < 2;j++)
    {
      for (i = 0; i < 10; i++)
        {
          sprintf(message, "MESSAGE %d\n\0", i);
          printf("MESSAGE SENT: %s", message);
          write(s, (void *) message, 12);
        }
    }

  releaseSocket( s );
  return ;

}

int bindSocket( int  port, char *host )
{
  int s;                  /* Network socket */
  int len;
  struct hostent *h;
  struct sockaddr_in s1;  /* socket address */

  if((h = gethostbyname(host)) == NULL)
    {
      perror("Problems resolving host name:");
      return -1;
    }

  /*
   * Bind address to remote end of socket
   */
  memset((void *)&s1, (int) '\0', sizeof(s1));
  s1.sin_port = htons(IPPORT_RESERVED + port);
  s1.sin_family = AF_INET;
  memcpy((char *) &s1.sin_addr, h->h_addr, h->h_length);

  /*
   * Create socket for InterProcess Communication
   */
  if ((s = socket(AF_INET, SOCK_STREAM, 0)) <= 0)
    {
      perror("socket error");
      return -1;
    }

  if (connect( s, (struct sockaddr *) &s1, sizeof(s1)) < 0)
    {
      perror("connect error");
      return - 1;
    }

  return s;

}

void releaseSocket( int f )
{
  close ( f );
  return ;
}

 
 
 

1. Help: Solaris's select() statement

[PLEASE DO NOT REPLY TO THIS ACCOUNT. IF YOU WISH TO SEND ME A MAIL,

Hi there,

I'm having a slight problem porting some code from AIX to Solaris. The
problem seems to lie in the differences between the AIX select()
statement and the Solaris one.

Here's the short section of code:

  ...
  bzero(&read, sizeof(read));
  read.fdsmask[0] = 1 << fd;           /* Set the input file descriptor*/
  read.msgids[0] = QHandle;            /* Also want to wait on the queue*/

  bzero(&write,sizeof(write));
  write.msgids[0] = -1;

  bzero(&exc,sizeof(exc));
  exc.fdsmask[0] = 1 << fd;            /* Set the input file descriptor*/
  exc.msgids[0] = QHandle;             /* Also want to wait on the queue*/

  nfdsmsgs = 1 + (1<<16);

  rc = select(nfdsmsgs
              ,(void *)&read
              ,(void *)&write
              ,(void *)&exc
              ,(struct timeval *)0
             )
  ...

Having looked at various manpages, and received numerous SEGV faults in
my tests, I do not think that a straight port is possible. This is because
select here is performing two functions - waiting on a file descriptor
and waiting on a message queue - whilst solaris's select statement seems
to only be capable of one function - waiting on a file descriptor.

Can anyone tell me how I would go about porting the above code to solaris.
Is there a routine in solaris that can wait on a message queue, or
can this be done in some way with the solaris select() routine?

All help is very much appreciated, Blake Evans-Pritchard

---

The opinions expressed above are mine, and may not necessarily be those
of my employer, IBM.

2. Problem mounting HFS filesystem

3. select statement in Solaris 2.4

4. 'sg' and terminal ID....what gives?

5. Thundering herd problem in select() for socket reads under Solaris?

6. lilo again

7. KSH select statement

8. Xterm not powerful enough for SLang

9. Select statement in ksh

10. DB2 SELECT statement on AIX

11. KSH select statement