user3429531
user3429531

Reputation: 355

socket programming getting input

I am trying to establish a connection between client and server and when once it's successful, a menu screen will be shown prompting the user whether he wants to 1)input a message 2)exit the program.

the problem I face was when I key in one, It will return me the output shown below

Client output(It will just keep returning "I got your msg whenever I enter '1' without having the user to input the message first until I press ctrl+c")

Main Menu
        ----------------------
 1. option 1
 2. option 2
 Enter your choice1
 Please enter the message: I got your msg
 Main Menu
        ----------------------
 1. option 1
 2. option 2
 Enter your choice1
 Please enter the message: I got your msg
 Main Menu
        ----------------------
  1. option 1
  2. option 2
  Enter your choice1
  Please enter the message: I got your msg

Server

  Here is the msg:

  Here is the msg:

  Here is the msg:

What I have currently.

server.c

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <stdbool.h>

void doPrcoessing(int sock) {
int n;
char buffer[256];
bzero(buffer,256);
n =read(sock,buffer,255);

if(n < 0) {
    perror("Error from reading socket");
    exit(1);
}

    printf("Here is the msg: %s\n",buffer);
    n=write(sock,"I got your msg",18);

if(n<0) {
    perror("Error writing to socket");
    exit(1);
}
}

int main( int argc, char *argv[] )
{
    int sockfd,pid,newsockfd,portno,clientn;
    struct sockaddr_in serv_addr,cli_addr;
    char buffer[256];
    bool connected;
    int n;

    /*call socket() function*/
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd < 0)
    {
    perror("Error opening socket");
    exit(1);
    }
   // printf("socket retrieve success\n");

   /*Initialize socket structure*/

    bzero((char *) &serv_addr, sizeof(serv_addr));
    portno = atoi(argv[1]);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);

    /*bind the host address using bind() call*/
    if(bind(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
    perror("Error on binding!");
        exit(1);
    }
    int yes =1;
    if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes, sizeof(yes)) == -1) {
    perror("setsockopt");
    exit(1);
    }
    /*start listening for clients, will go into sleep mode and wait for incoming     connection*/
    listen(sockfd,5);
clientn = sizeof(cli_addr);    
 while(connected == false) {
    newsockfd = accept(sockfd,(struct sockaddr*)&cli_addr,&clientn);

    if(newsockfd < 0) {
        perror("Error on accept!");
        exit(1);
        }

    /*Create chlid process*/
    pid =fork();
    if(pid < 0)
    {
        perror("Error on fork!");
        exit(1);
    }
    if(pid == 0)
    {
        /*Client process*/
        close(sockfd);
        doPrcoessing(newsockfd);
        return 0;   
    }
    else
    {
        close(newsockfd);
    }
}
return 0;

}

client.c

#include <sys/socket.h> 
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netdb.h>
#include <stdbool.h>

void print(void);

int sockfd, portno, n; 
struct sockaddr_in serv_addr;
struct hostent *server;
bool loop = false; 
char options[100];
char buffer[256];

int main(int argc, char *argv[])
{  
while(loop==false) {
    if (argc < 3) {
        fprintf(stderr,"usage %s hostname port\n", argv[0]);
        exit(0);
    }
    portno = atoi(argv[2]);
 /* Create a socket point */
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)  {
        perror("ERROR opening socket");
        exit(1);
  }
 server = gethostbyname(argv[1]);
 if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
 }

 bzero((char *)&serv_addr, sizeof(serv_addr));
 serv_addr.sin_family = AF_INET;
 bcopy((char *)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,
            server->h_length);
    serv_addr.sin_port = htons(portno);

 /* connect to the server */
    if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) {
        perror("Error connecting");
        exit(1);
 }

int choice;  
//print();
    if(choice !=2) {
        printf("Main Menu");
        printf("\n\t----------------------");
        printf("\n 1. option 1");
        printf("\n 2. option 2");
        printf("\n Enter your choice");
        scanf("%d",&choice);
        switch(choice) {
        case 1: print();
            break;
        case 2: exit(0);
            break;
        default: printf("Invalid choice!\n");
            break;

        }   
    }
}
close(sockfd);
    return 0;
}

void print(void)    {
 /*ask for a message from the user, this message will be read by server */
printf("Please enter the message: ");
        bzero(buffer,256);
            fgets(buffer,255,stdin);
        /* Send message to the server */
            n = write(sockfd,buffer,strlen(buffer));
        if (n < 0)  {
                perror("ERROR writing to socket");
                exit(1);
            }

        /* read server response */
            bzero(buffer,256);
            n = read(sockfd,buffer,255);
            if (n < 0)  {
                perror("ERROR reading from socket");
                exit(1);
            }

        printf("%s\n",buffer);  
}

Upvotes: 0

Views: 8800

Answers (2)

CobbLiu
CobbLiu

Reputation: 457

The reason WHY fgets() fails to read buffer from input is that your scanf left a new line character in input buffer.

So your fgets will return soon after calling it.

codes in client.c should be modified as below:

<code...>
printf("Please enter the message: \n");  
fflush(stdout);  
bzero(buffer,256);  
read(STDIN_FILENO, buffer, sizeof(buffer));  
/* Send message to the server */  
n = write(sockfd,buffer,strlen(buffer));  
</code...>

also, codes in server.c should be modified as below:

<code...>
scanf("%d ", &choice);
</code...>

Upvotes: 2

William Pursell
William Pursell

Reputation: 212178

scanf does not consume the newline that the user hits after making a selection. But the fgets immediately does, and nothing else. The correct solution is to stop using scanf (that's the correct solution for any program that uses scanf, IMO). But it's probably simpler to add a space to the format string:

scanf( "%d " ... )

Upvotes: 1

Related Questions