LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-08-2006, 02:05 PM   #1
harvest
LQ Newbie
 
Registered: Sep 2006
Posts: 8

Rep: Reputation: 0
function poll() trouble


Code:

/*
* serv.c - server creating AF_UNIX socket used by cli.c
* compile with gcc -g -Wall serv.c -o serv
* command line option: max number of clients allowed
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/poll.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

#define UN_PATH "./usock"

static void add_flags ( int fd, int flags ) {
  int val;

  if (( val = fcntl ( fd, F_GETFL, 0 )) < 0 ) {
    perror ("add_flags (): fcntl ( F_GETFL )");
    exit(1);
  }
  val |= flags;
  if (( val = fcntl ( fd, F_SETFL, val )) < 0 ) {
    perror ("add_flags (): fcntl ( F_SETFL )");
    exit (1);
  }
}

int main ( int argc, char *argv[] ) {
  struct sockaddr_un  sa;
  struct pollfd      *pfd;
  socklen_t           cli_len;
  int                 srv, len, cli, cli_num, cli_now, n, l;
  char                buf[256];

  ( void )unlink ( UN_PATH );

  if (( argc != 2 ) || (( cli_num = atoi ( argv[1])) == 0 )) cli_num = 1;
  printf ( "Up to %d client(s) allowed\n", cli_num );
  
  cli_num++;   // one more for listen
  if (( pfd = ( pollfd * )calloc ( cli_num, sizeof ( pollfd ))) == NULL ) {
    perror ("calloc ( pollfd )");
    exit (1);
  }

  srv = socket ( PF_UNIX, SOCK_STREAM, 0 );
  if ( srv < 0 ) {
    perror ("socket ( PF_UNIX, SOCK_STREAM )");
    exit (1);
  }
  if ( fcntl ( srv, F_SETOWN, getpid ()) < 0 ) {
    perror ("fcntl ( s, F_SETOWN )");
    exit (1);
  }

  len = sizeof ( sa );
  sa.sun_family = AF_UNIX;
  strcpy ( sa.sun_path, UN_PATH );
  if ( bind ( srv, ( struct sockaddr * )&sa, len ) < 0 ) {
    perror ("bind ()");
    exit (1);
  }
  fprintf ( stderr, "bind () OK\n");

  if ( listen ( srv, 2 * cli_num + 3 ) < 0 ) {
    perror("listen ()");
    exit (1);
  }
  fprintf ( stderr, "listen () OK\n");

  pfd[0].fd = srv;
  pfd[0].events = POLLRDNORM;
  cli_now = 0;
  
  fprintf ( stderr, "Initializing loop:");
  for ( int i = 1; i < cli_num; i++ ) { 
    fprintf ( stderr, "." );
    pfd[i].fd = -1;
  }  
  fprintf ( stderr, "\nEntering loop\n");
  for ( ;; ) {
    n = poll ( pfd, cli_now + 1, -1 ); // no tmo
    fprintf ( stderr, "Aha!\n");
    if ( pfd[0].revents & POLLRDNORM ) { // new client
		  if ( cli_now < cli_num ) {
        if (( cli = accept ( srv, NULL, NULL )) < 0 ) perror ("accept()");
  		  else {
  		    fprintf ( stderr, "accept() OK\n: " );
          for ( int i = 1; i < cli_num; i++ ) { 
            if ( pfd[i].fd == -1 ) { 
              pfd[i].fd = cli;
              pfd[i].events = POLLRDNORM;
              cli_now++;
              fprintf ( stderr, "client#%d\n", cli_now );
              break;
            }
          }
        }
      }
      else fprintf ( stderr, "Too many clients\n" );
      if ( n == 1 ) continue;
    }
    for ( int i = 1; i < cli_num; i++ ) { 
//fprintf ( stderr, "." );
      if (( cli = pfd[i].fd ) < 0 ) continue;   
//      fprintf ( stderr, "pfd[%d].revents=%X\n", i, pfd[i].revents );
      if ( pfd[i].revents & ( POLLRDNORM | POLLERR )) {
        l = read ( cli, buf, sizeof ( buf ));
        if ( l < 0 ) {
          if ( errno == ECONNRESET ) {   // connection reset by client
            close ( cli );
            pfd[i].fd = -1;    
            cli_now--;
            fprintf ( stderr, "connection reset by client\n" );
          }
          else perror ("read()");
        }
        else if ( l == 0 ) {
          close ( cli );
          pfd[i].fd = -1;    
          cli_now--;
          fprintf ( stderr, "connection closed by client\n" );
        }
        else {
          buf[l++] = '\n';
          buf[l] = 0;
          fprintf ( stderr, "%s", buf );
        }
        if ( --n <= 0 ) break;
      }
    }
  }
/* not reached */
  return 0;
}

/*************************/
/*
* cli.c - client creating AF_UNIX socket
* compile with gcc -g -Wall cli.c -o cli
* command line option: client name
*/


#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define USOCK "./usock"

int main ( int argc, char *argv[]) {
  int    fd, len;
  FILE   *file;
  struct sockaddr_un sa;
  
  char buf1[50] = "hello from client ";
  int len1 = strlen ( buf1 );

  if( argc > 1 ){
    strcpy ( buf1 + len1, argv[1]);
    len1 = strlen(buf1);
  }
  
  fd = socket ( PF_UNIX, SOCK_STREAM, 0 );
  if ( fd < 0 ) {
    perror ("cli: socket ( PF_UNIX,SOCK_STREAM)");
    exit (1);
  }
  file = fdopen(fd, "wb+");
  if ( file == NULL ) {
    printf ("FILE fdopen failed\n");  
    exit (1);
  }
  sa.sun_family = AF_UNIX;
  strcpy ( sa.sun_path, USOCK );
  len = sizeof ( sa );
  if ( connect ( fd, ( struct sockaddr *)&sa, len ) < 0 ) {
    perror ("cli: connect()");
    exit (1);
  }
  
  for ( ;; ) {
    static unsigned long int count = 1;
    sleep ( 1 );
    printf ("Sent message #%d\n", count++ );
    if ( write ( fd, buf1, len1 ) != len1 ) {
      perror("cli: send(buf1)");
      exit(1);
    }
    fflush ( file );
  }
  return 0;
}
Start server with the option 2: ./serv 2
Start client with the option A: ./cli A
Server now is getting messages from client A
Start client with the option B: ./cli B
Server now is getting messages from both clients A and B

Terminate client B ( press ctrl+C )
Server now is getting messages from client A
Start client with the option B: ./cli B
Server now is getting messages from both clients A and B

Terminate client A ( press ctrl+C )
NOTHING IS COMING TO THE SCREEN!!!

Start client with the option A: ./cli A
Server now is getting messages from both clients A and B and from the client B you can get everything send while client A was off. My investigation showed that server was stock in the function call poll().
What do I do wrong or what I didn't get from the description of poll()
Thanks.
 
Old 10-08-2006, 03:42 PM   #2
harvest
LQ Newbie
 
Registered: Sep 2006
Posts: 8

Original Poster
Rep: Reputation: 0
Below is updated code. It does what it should do. The question remains: why the original code does NOT work. The function poll() description does NOT require to do what makes it work. I'm totally confused.
Hey, NIX Guru, I want to hear from you!
Code:
                                                              /*
* serv.c - server creating AF_UNIX socket used by cli.c
* compile with gcc -g -Wall serv.c -o serv
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/poll.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

#define UN_PATH "./usock"

static void add_flags ( int fd, int flags ) {
  int val;

  if (( val = fcntl ( fd, F_GETFL, 0 )) < 0 ) {
    perror ("add_flags (): fcntl ( F_GETFL )");
    exit(1);
  }
  val |= flags;
  if (( val = fcntl ( fd, F_SETFL, val )) < 0 ) {
    perror ("add_flags (): fcntl ( F_SETFL )");
    exit (1);
  }
}

int main ( int argc, char *argv[] ) {
  struct sockaddr_un  sa;
  struct pollfd      *pfd;
  socklen_t           cli_len;
  int                 srv, len, cli, cli_num, cli_now, n, l;
  char                buf[256];

  ( void )unlink ( UN_PATH );

  if (( argc != 2 ) || (( cli_num = atoi ( argv[1])) == 0 )) cli_num = 1;
  printf ( "Up to %d client(s) allowed\n", cli_num );
  
  cli_num++;   // one more for listen
  if (( pfd = ( pollfd * )calloc ( cli_num, sizeof ( pollfd ))) == NULL ) {
    perror ("calloc ( pollfd )");
    exit (1);
  }

  srv = socket ( PF_UNIX, SOCK_STREAM, 0 );
  if ( srv < 0 ) {
    perror ("socket ( PF_UNIX, SOCK_STREAM )");
    exit (1);
  }
  if ( fcntl ( srv, F_SETOWN, getpid ()) < 0 ) {
    perror ("fcntl ( s, F_SETOWN )");
    exit (1);
  }

  len = sizeof ( sa );
  sa.sun_family = AF_UNIX;
  strcpy ( sa.sun_path, UN_PATH );
  if ( bind ( srv, ( struct sockaddr * )&sa, len ) < 0 ) {
    perror ("bind ()");
    exit (1);
  }
  fprintf ( stderr, "bind () OK\n");

  if ( listen ( srv, 2 * cli_num + 3 ) < 0 ) {
    perror("listen ()");
    exit (1);
  }
  fprintf ( stderr, "listen () OK\n");

  pfd[0].fd = srv;
  pfd[0].events = POLLRDNORM;
  cli_now = 0;
  
  fprintf ( stderr, "Initializing loop:");
  for ( int i = 1; i < cli_num; i++ ) { 
    fprintf ( stderr, "." );
    pfd[i].fd = -1;
  }  
  fprintf ( stderr, "\nEntering loop\n");
  for ( ;; ) {
    n = poll ( pfd, cli_now + 1, -1 ); // no tmo
    fprintf ( stderr, "Aha!\n");
    if ( pfd[0].revents & POLLRDNORM ) { // new client
		  if ( cli_now < cli_num ) {
        if (( cli = accept ( srv, NULL, NULL )) < 0 ) perror ("accept()");
  		  else {
  		    fprintf ( stderr, "accept() OK\n: " );
#if 0
          for ( int i = 1; i < cli_num; i++ ) { 
            if ( pfd[i].fd == -1 ) { 
              pfd[i].fd = cli;
              pfd[i].events = POLLRDNORM;
              cli_now++;
              fprintf ( stderr, "client#%d\n", cli_now );
              break;
            }
          }
#else
          pfd[++cli_now].fd = cli;
          pfd[cli_now].events = POLLRDNORM;
          fprintf ( stderr, "client#%d\n", cli_now );
#endif          
        }
      }
      else fprintf ( stderr, "Too many clients\n" );
      if ( n == 1 ) continue;
    }
    for ( int i = 1; i < cli_num; i++ ) { 
//fprintf ( stderr, "." );
      if (( cli = pfd[i].fd ) < 0 ) continue;   
//      fprintf ( stderr, "pfd[%d].revents=%X\n", i, pfd[i].revents );
      if ( pfd[i].revents & ( POLLRDNORM | POLLERR )) {
        l = read ( cli, buf, sizeof ( buf ));
        if ( l < 0 ) {
          if ( errno == ECONNRESET ) {   // connection reset by client
            close ( cli );
            pfd[i].fd = -1;    
            cli_now--;
            fprintf ( stderr, "connection reset by client\n" );
          }
          else perror ("read()");
        }
        else if ( l == 0 ) {
          close ( cli );
#if 0
          pfd[i].fd = -1;
#else
          if ( i < cli_now ) {
            memcpy ( &pfd[i], &pfd[cli_now], sizeof ( pollfd ));
            pfd[cli_now].fd = -1;
          }    
#endif
          cli_now--;
          fprintf ( stderr, "connection closed by client\n" );
        }
        else {
          buf[l++] = '\n';
          buf[l] = 0;
          fprintf ( stderr, "%s", buf );
        }
        if ( --n <= 0 ) break;
      }
    }
  }
/* not reached */
  return 0;
}
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How do I run a function within a function arguement? C/C++ RHLinuxGUY Programming 12 05-19-2006 02:29 PM
what are the Hexadecimal function and ASCII function in Perl Bassam Programming 1 06-03-2004 01:44 AM
A main can be changed by a function local without passing anything to the function? ananthbv Programming 10 05-04-2004 01:31 PM
Is the wait function is the same as the sleep function ? Linh Programming 3 04-28-2004 12:39 PM
Perl exec function in linux (and system-function) nazula Programming 1 04-19-2004 12:21 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:23 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration