Reputation: 355
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
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
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