Looping problems socket programming in C

Sorry if I posted 2 separate questions.
I'm currently doing socket programming on my current task. As you can see below in the client side. I've tried to do a loop so I will be able to get prompt for input over and over again.
This is the code.

do{ 
 
    
   printf("Please your name > "); 
   scanf("%s",name); 
    
   write(clientFd,name,strlen(name)); 
 
    
   }while(strcmp("exit",name)!=0);

It worked for the first time, but the second time it asked me for input but it did not print anything on the server side. After entering the second input it exited from the terminal.

I've check up the loop and realize it was the write problem. Any way to solve this?

From the code snipit you posted it's difficult to say what is happening. My only guess what you've provided is that the space allocated for name isn't large enough to handle the string that you entered.

It would help if you could post the whole routine which would include the declaration of name, as well as the two strings that you entered from the tty.

Add:

ret = write(clientFd,name,strlen(name));
printf("Write ret: %d\n", ret);

Also with this loop you will write 'exit' to the fd. Maybe use a while(1) { } and place

while (1) {
    int ret;

    /* input stuff */

    if (strcmp(name, "exit") == 0)
        break;
    ret = write(clientFd,name,strlen(name));
    if (ret == -1) perror("write");
    printf("Write returned: %d\n", ret);
}

It also may help to issue a read() to ensure the socket is available... My guess is that you're getting a SIGPIPE by writing to a broken socket. you can set SO_NOSIGPIPE with setsockopt

Hahaha its still not working..

The client side

while(1){

   int ret;
   char country[300];


   printf("Please enter country name > ");

   scanf("%s",country);

   if (strcmp(country, "exit") == 0)
   break;
   else
   ret = write(clientFd,country,strlen(country));
   //f (ret == -1) perror("write");
   //printf("Write returned: %d\n", ret);    

   

   //write(clientFd,country,strlen(country));

   }

Server Side

readData();

            bzero(country,300);

            c=read(clientFd,country,300);

	    printf("You have entered: %s\n",country);

            printf ("%s Capital       : %s\n", country,getCapital(country));

            printf ("%s Currency Code : %s\n", country,getCurrencyCode(country));

            char* capital = getCapital (country);

	    char* currency = getCurrencyCode(country);



            close (clientFd); /* Close the socket */

            exit (/* EXIT_SUCCESS */ 0); /* Terminate */

So like what you all said it might be the reading part that is the the problem.
From what I think is just the read problem?
Reason is I comment the write link it just run the loop normally.

The server reads once and exits... So the client can't loop if the server doesn't...

haha sry i did post the whole thing i did try to loop thou.

   

char country[300];

char capital[300];

char currency[300];

 while (1) /* Loop forever */

      {

        /* Accept a client connection */

        clientFd = accept (serverFd, clientSockAddrPtr, &clientLen);



        if (fork () == 0) /* Create child to send recipe */

          {

            readData();

            bzero(country,300);

            c=read(clientFd,country,300);

	    printf("You have entered: %s\n",country);

            printf ("%s Capital       : %s\n", country,getCapital(country));

            printf ("%s Currency Code : %s\n", country,getCurrencyCode(country));

            char* capital = getCapital (country);

	    char* currency = getCurrencyCode(country);



            close (clientFd); /* Close the socket */

            exit (/* EXIT_SUCCESS */ 0); /* Terminate */

          }

        else

          close (clientFd); /* Close the client descriptor */

      }

   }

it still looks to me that your loop only is for accepting new connections and still only reads a connection ONCE then exits...

I generally don't have a need for a fork() and use select() in the main loop. You can use select() in your child too. It'll sleep until something is available to read.

man 2 select

So ya mean I need to remove the close socket?
I've tried commenting it and found out that it's the read data problem is that true.
I'm not really familiar with the C programming commands so kinda confused with it.
Mind guiding me along?

while (1) /* Loop forever */

      {

        /* Accept a client connection */

        clientFd = accept (serverFd, clientSockAddrPtr, &clientLen);
	



        //if (fork () == 0) /* Create child to send recipe */

          //{

            
	    readData();

            bzero(country,300);

            c=read(clientFd,country,300);

	    printf("You have entered: %s\n",country);

            printf ("%s Capital       : %s\n", country,getCapital(country));

            printf ("%s Currency Code : %s\n", country,getCurrencyCode(country));

            char* capital = getCapital (country);

	    char* currency = getCurrencyCode(country);



            //close (clientFd); /* Close the socket */

           //exit (/* EXIT_SUCCESS */ 0); /* Terminate */

          //}

        //else

          //close (clientFd); /* Close the client descriptor */

      }

   }

Readdata function

void readData ()

{

	FILE * pFile;

	NoOfRecordsRead = 0;

   	char buffer [Line_Char_Buffer_Size];



	pFile = fopen (INPUT_FILE_NAME , "r");

   

	if (pFile == NULL) 

		perror ("Error opening file 'Countries.txt' !");

	else

	{

		while ( !feof (pFile) )

     	{

			char* aLine = get_line (buffer, Line_Char_Buffer_Size, pFile);



			if (aLine != NULL)

			{

				globalCountryDataArray [NoOfRecordsRead++] = createCountryRecord (aLine);

			}

     	}



     fclose (pFile);

	

	}

}

nooo. you do need to loop to accept new connections. maybe something like (untested):

while (1) /* Loop forever */
{
	/* Accept a client connection */
	clientFd = accept(serverFd, clientSockAddrPtr, &clientLen);

	if (fork () == 0) /* Create child to read */
	{
		readData();
		memset(country, 0, 300);
		while ((c = read(clientFd, country, 300)) > 0)
		{
			char *capital = getCapital(country);
			char *currency = getCurrencyCode(country);

			printf("You have entered: %s\n",country);
			printf ("%s Capital       : %s\n", country, capital);
			printf ("%s Currency Code : %s\n", country, currency);
		}
		perror("read");
		close(clientFd);	/* Close the socket */
		exit(0);		/* Terminate child */
	} else {
		perror("fork");
		close(clientFd);	/* Close the client descriptor */
	}
}
1 Like

It works thanks!! But got a slight problem
The list of output has shown.
I've tried typing the input lets say, Vietnam.
It works for the first time.
The 2nd time I typed Singapore, it works too.
However on the 3rd try, I typed Vietnam again.
It shows Vietnamre which shows that it cannot be found and the re of the previously Singapore is added behind Vietnam.
I've tried entered Netherlands and it works.
When I typed back Vietnam again the letters behind is added with ands.

I've declared the char country to 300 but it' still not working though:wall:

Please enter country name > Vietnam
Please enter country name > Singapore
Please enter country name > Vietnam
Please enter country name > Netherlands


You have entered: Vietnam
Vietnam Capital       : Hanoi
Vietnam Currency Code : VND
You have entered: Singapore
Singapore Capital       : Singapore
Singapore Currency Code : SGD
Country 'Vietnamre' not found!
Country 'Vietnamre' not found!
You have entered: Vietnamre
Vietnamre Capital       : (null)
Vietnamre Currency Code : (null)
You have entered: Netherlands
Netherlands Capital       : Amsterdam
Netherlands Currency Code : EUR
You have entered: Vietnamands
Vietnamands Capital       : (null)
Vietnamands Currency Code : (null)

Ah yes of course. You will want the memset() also at the end of that while loop. Or, at beginning you may do country[c]=0 to null terminate it there.

Also while thinking about it, is best to use sizeof(country) in place of the 300 in memset and read. You want to also save 1 byte for NUL termination so in read() replace 300 with "sizeof(country)-1" this is so that if you ever change the size, you only need to change it in 1 place. The rest is taken care of by the compiler.