UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

  • Index
  • » C
  • » Terminates a socket and a function help

#1 2009-11-10 06:10 PM

bufoss
Member
Registered: 2009-11-10
Posts: 4

Re: Terminates a socket and a function help

Hi,
I am trying to make a program with sockets. An user (client mode) decides from 3 operations if he wants to create account, deposit or quit.

The problem I have is that when he press Q , the program does not exit.

Also , I would like when a user press D make a function so as to insert info account like name, id, money in a struct , to send this info via buffer buf to server and server print that.

Another problem I have is when I press ctrl^c in client  , my server goes in infinite loop printing 'Cliend send'

Could someone help me please ?
Thank you 

//client.c
#include <sys/types.h>     
#include <sys/socket.h>    
#include <sys/un.h>        
#include <stdio.h>         
#include <stdlib.h>	   
#include <time.h>
#include <errno.h>

enum { CREATE = 'D', DEPOSIT = 'K',  QUIT = 'Q' } ;

int get_choice();

main(int argc, char *argv[])
{
	int sock,serverlen;
	char buf[256];
        int quit = 0 ;


	struct sockaddr_un server;
	struct sockaddr *serverptr;

	if(argc != 2){
		exit(1);
	}

	sock = socket(AF_UNIX, SOCK_STREAM, 0);
	server.sun_family = AF_UNIX;
	strcpy(server.sun_path, argv[1]);
	serverptr = (struct sockaddr *) &server;
	serverlen = sizeof server;
	connect(sock,serverptr,serverlen);

	while( !quit )
       {
      int choice ;
      

      printf("D. CREATE\n");
      printf("K. DEPOSIT\n");
      printf("Q. QUIT\n");



      choice = get_choice() ;

      switch( choice )
      {
          case CREATE: printf("CREATE\n");
              break ;
          case DEPOSIT: printf("DEPOSIT\n");
              break ;
          case QUIT: printf("QUIT\n");
              quit = 1 ;
              break ;
      }
  

	printf("%d\n", choice);

	buf[0]=choice;

	write(sock,buf,sizeof buf);
	
bzero(buf, sizeof buf);
	read(sock,buf,sizeof buf);
	}


	close(sock); 
	exit(0);
 
}

int get_choice()
{
 int choice = 0 ;
 const char* const valid_choices = "CDQ" ;

 do
 {
   fputs( "Your choice : ", stdout ) ;
   fflush( stdin ) ;
   choice = toupper( fgetc( stdin ) ) ;
   fgetc( stdin ) ; /* discard newline */

   if( strchr( valid_choices, choice ) == NULL )
   {
     fputs( "invalid option\n", stdout ) ;
     choice = 0 ;
   }
 } while( choice == 0 ) ;

 return choice ;
}
//server.c
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>

void sigchld_handler();

main(int argc, char *argv[])
{
	int sock,newsock,serverlen,clientlen;
	char buf[256];

	struct sockaddr_un server, client;
	struct sockaddr *serverptr, *clientptr;

	
	if(argc != 2){
		exit(1);
	}

	signal(SIGCHLD, sigchld_handler);
	
	sock = socket(AF_UNIX, SOCK_STREAM, 0);
	server.sun_family = AF_UNIX;
	strcpy(server.sun_path, argv[1]);
	unlink(argv[1]);
	serverptr = (struct sockaddr *) &server;
	serverlen = sizeof server;
	bind(sock,serverptr,serverlen);
	listen(sock,1);
	
	printf("I am waiting connections ...\n");
		
	while(1){
		clientptr = (struct sockaddr *)&client;
		clientlen = sizeof client;

	
		while((newsock = accept(sock,clientptr,&clientlen)) < 0);
		printf("\nNew connection.\n");
		

		switch(fork()){

			case -1 :
				exit(1);

			case 0 :
				do{
					bzero(buf,sizeof buf);
					read(newsock,buf,sizeof buf);
					
					printf("Client sent  %s.\n",buf);


				}while(buf[0] != 81);

				close(newsock); 
				exit(0);
		}

	}
}


void sigchld_handler()
{
	int status;
	wait(&status);
}

Offline

#2 2009-11-10 09:55 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Terminates a socket and a function help

Your server needs a default: case in the switch(fork()), so that the parent process
does close(newsock)...  As it is now, the parent is keeping an open copy of the
socket around, so even when the child closes it and exits, the connection stays
alive...

Also, you never send any kind of reply back to the client, but it sits there trying to
read one...  That, combined with the held open connection by the parent is where
the client is hanging, and why it's not exiting...  If the parent had closed its copy of
the socket, then the client's read() would fail, and you'd bust out of your loop...  Or,
if you sent a reply from the server child before exiting, it'd work, too...

But, you really don't need to be sending the full 256-byte buffer back and forth,
when all you're transmitting is a single character, either...  That's just wasteful...
Change the write() length to 1; or, if you need to treat it as null-terminated on the
server (like you do with that printf("%s")), then set the second byte of the buffer to
'\0', and the write() length to 2...  (Or, just have the server add the null char based
on the read() return value...)

Also, you really want to be checking the return values for all your I/O operations...
read()/write() on sockets can return a short count...  (It's far less likely on a Unix
domain socket, like you're using, instead of a TCP socket, but still it's possible...)
At a bare minimum, at least check for failure returns (-1) and EOF (0 from read())...
If you're only sending 1 byte messages back and forth, that's actually all you need
anyway, since there's no possibility of a short read/write with only a single byte in
play...

Offline

#3 2009-11-11 04:10 PM

bufoss
Member
Registered: 2009-11-10
Posts: 4

Re: Terminates a socket and a function help

Could you help with code  for this ?

Thanks a lot

Offline

#4 2009-11-11 09:10 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Terminates a socket and a function help

I'm not going to write all your code for you...  None of us actually get paid to work here,
you realize? ;-)

But, add this to your server switch():

default:
    close (newsock);
    break;

Change your server child's read() to this:

int i; /* define this somewhere at the top of an in-scope code block */
/* ... */
i = read (newsock, buf, sizeof (buf) - 1);
if (i <= 0) {
    printf ("Client disconnected\n");
    break;
}
buf[i] = '\0';

You can get rid of the bzero() then, as well...

That will solve your immediate problems...  If you want to add other behavior, like
sending additional data from the client for certain commands, then you'll need to
first define a protocol that both client and server agree on...  I don't know enough
about your design goals to begin to tell you how to go about it...  You need to
decide if you can get away with fixed-sized messages big enough to contain any
data you might ever need to send, or if they need to be variable length...  If they
need to be variable, you need to decide if you want to send a leading message
length header or if you want a delimiter to mark the end of each message...  And,
you'll need to decide on the layout of the actual messages...  Right now, you're
just sending a single char...  That's easy enough to deal with...  But, if you start
sending more than that, you need to carefully define the layout of the messages,
and both sides need to adhere to it...

Offline

#5 2009-11-14 07:38 PM

bufoss
Member
Registered: 2009-11-10
Posts: 4

Re: Terminates a socket and a function help

Thanks a lot

Anothe question (final)
I use the functions write and read so as to take place communication between client and server.
But how can I write integer to buffer ?
For example I have a variable     int number =34;
and from write declaration I have to use char *.

//write(int file_descriptor, char *buffer, size_t buffer_length)

And what about sending a structure. How can I do it ?

Thanks again

Offline

#6 2009-11-14 08:06 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Terminates a socket and a function help

/* in the sender */
int i, in;
short s, sn;
/* ... somewhere along the way, "i" and "s" get set to some values... */
in = htonl (i);
sn = htons (s);
printf ("Sending i = %d, s = %hd\n", i, s);
write (sockfd, &in, sizeof (in));
write (sockfd, &sn, sizeof (sn));

/* in the receiver */
read (sockfd, &in, sizeof (in));
read (sockfd, &sn, sizeof (sn));
i = ntohl (in);
s = ntohs (sn);
printf ("Received i = %d, s = %hd\n", i, s);

Offline

#7 2009-11-14 08:16 PM

bufoss
Member
Registered: 2009-11-10
Posts: 4

Re: Terminates a socket and a function help

Perfect!
Thanks for all

Offline

  • Index
  • » C
  • » Terminates a socket and a function help

Board footer

Powered by FluxBB