0

I have written a server/client based c program. The basic function of the program is that client will send a character e.g to server, The server will increment it and send the character back. So if a client sends 'a' it will receive 'b'. But when the client sends a 'q' the server is supposed to close the connection. The program is doing what its supposed to do but on client side its printing "Enter a character" and "Character from server" twice. Also sending a 'q' does close the connection but only if you send it for the second time.

Here is the server side code

void *client_thread(void *client_sockfd){
    int socket=*(int *)client_sockfd;
    while(1){
        read(socket, &ch, 1);
        if(ch=='q')
        {
            close(socket); 
        }
        else 
        {
            ch++;
            write(socket, &ch, 1);
        }
    }
    //close(socket);
    printf("Connection closed with %d",socket);       

}//end fucntion

client side code

while(1)
{
    printf("Enter a character");
    scanf("%c",&ch);  
    write(sockfd, &ch, 1);
    read(sockfd, &ch, 1);
    printf("char from server = %c\n", ch);

    //  close(sockfd);
    //exit(0);
}
if(ch=='q'){
    printf("Server closed the connection");
}
1
  • You might want to add some code to check that the reads and writes actually succeeded Commented May 30, 2015 at 9:47

4 Answers 4

1

The scanf is reading one character at a time, so when you type a character and press enter, the first cycle will read the character, the second one will read the newline.

You can use

scanf("%c%*c", &ch);

that reads the two characters, but stores only the first one.

3
  • this worked for not printing twice but now its closing the connection on random character.
    – Ali Rehman
    Commented May 30, 2015 at 10:06
  • use this while((n = read(sockfd, &ch, 1))>0) instead of while(1) @AliRehman
    – Subinoy
    Commented May 30, 2015 at 10:15
  • where exactly do i have to use it?
    – Ali Rehman
    Commented May 30, 2015 at 10:21
0

Client Side: Here the two lines are printed because there are two inputs one is your character and second is enter or \n

So use scanf("%c%c",&ch); in the client side.

Server Side: And second use while((n = read(sockfd, &ch, 1))>0) to stop it from terminating the connection automatically. The read statement returns the number of bytes read.

Because the value you provide is not erased after getting increment. The reason is:

  • Suppose your input is a, then the server responses b to you and as you are not checking the return value of read in the server side, so it increments ch every time and as it reaches q and the socket gets closed.
  • When the server increments the value it also sends it to client but as the client is in scanf mode it can't get the input until the read statement, for this reason you can't see the automated increment value. And the increment is so fast that before your next input the socket already have been terminated.
3
  • Thanks alot. Its working fine now. I have also edited the while loop in client side while(m>0) where m has the return value of client side read. It isnt doing anything out of ordinary but do tell me if its okay to do so. @Subinoy
    – Ali Rehman
    Commented May 30, 2015 at 10:43
  • Always use the return values of functions. It's good for program. :-)
    – Subinoy
    Commented May 30, 2015 at 10:45
  • The while in client side will wait until the server response and till then you can't give inputs @AliRehman
    – Subinoy
    Commented May 30, 2015 at 10:58
0
printf("Enter a character");
scanf("%c",&ch); 

You actually enter two characters here, one for each key you press, the second of which is from Enter, and that is a newline, /n. This is why every other output from

printf("char from server = %c\n", ch);

Is probably:

char from server =

Then there's a blank line, then another output. If you did this instead:

printf("char from server = %d\n", (int)ch);
                       //   ^ not %c

The cast to int is not really necessary there but stresses the idea; you'll now get the decimal ASCII value of the character, and every other line will now be:

char from server = 10

That's the newline. For a way to deal with this issue, which has caught up countless C neophytes before you, see my answer here.

0

Your program is doing the following...

  1. Prints the message, "Enter a character" and blocks waiting for STDIN
  2. User types 'a' and '\n' - scanf() does not return control until a newline
  3. Writes 'a', reads 'b', prints 'b' and then prompts "Enter a character"
  4. Scanf has a character already (\n) so it returns immediately
  5. Writes '\n', reads '\n'+1, prints '\n'+1 and prompts "Enter a character"
  6. Repeats from 1.

This is why you see "Enter a character" twice.

As for having to send 'q' twice, your server loop does not exit when it receives the 'q', it calls close and continues reading. Each read after that will fail and return immediately with an error code. Similarly, your client loop doesn't break out.

Capture and test your return values. Also, step through with a debugger - this will answer many of your questions about C without having to wait for the forums to respond.

Not the answer you're looking for? Browse other questions tagged or ask your own question.