ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
/*
* 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.
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;
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.