Abhishek Gupta Abhishek Gupta - 2 months ago 12
C Question

Esoteric C program behavior while running - Code is not running sequentially

I am making a server chat application with register log-in system. While running the client code : I first selected to register and then after successful register ,client code promt me for login. Then I login and it worked fine . I have implemented these two things in an if else block in client code . After this I am doing some thing where I met with the one of the most attractive error my C life. Here is my source code in which I have marked the area with error (in end of the

main
function) and also mentioned the problem there (with code definition of the problem is easy).

I have also post the output after the code.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <time.h>
#define PORT "1618" //the port client will be connecting to
#define MAXDATASIZE 100 // max number of bytes we can get at once

static const int BUFFER_SIZE = 16*1024;
//get sockaddr ,IPv4 or IPv6:




void *get_in_addr(struct sockaddr *sa)
{
if(sa->sa_family ==AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}

return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int registerYourself(int sockfd)
{
printf("2\n");
char username[50], password[50],registerStatus[2];
int return_value,choice;
printf("You have chosen to register yourself\n");
printf("Please enter a username and password\n");
printf("Username:");
scanf("%s",username);
//printf("You entered %s\n",username);
send(sockfd,username,sizeof(username),0); // sending username
printf("\nPassword:");
scanf("%s",password); //sending password
//printf("-- %s\n",password);
send(sockfd,password,sizeof(password),0); //sending password
recv(sockfd,registerStatus,sizeof(registerStatus),0);//receiving from server that register is successful or not
if(strcmp(registerStatus,"1")==0) //If register successful then promoting for log-in
{
printf("Registration successfull\n Please Log in\n");
return_value=login(sockfd);
return return_value;
}
else if(strcmp(registerStatus,"0")==0)// Asking user what to do
{
printf("Username already taken...Please try again with other username...\nPress:\t 1 to try again\n\t2 to quit");
scanf("%d",&choice);
switch(choice)
{
case 1:
send(sockfd,"1", 2, 0);
registerYourself(sockfd);
break;
case 2:
send(sockfd,"0",2,0);
return 0;
}
}
}

int login(int sockfd)
{
printf("3\n");
char username[50],password[50],login_status[2];
int choice;
printf("You have chosen to login yourself\n");
printf("Please enter a username and password\n");
printf("Username:");
scanf("%s",username);
// printf("-- %s\n",username);
send(sockfd,username,sizeof(username),0);
send(sockfd,username,sizeof(username),0);//send username
printf("\nPassword:");
scanf("%s",password);
//printf("-- %s\n",password);
send(sockfd,password,sizeof(password),0);//send password
recv(sockfd,login_status,sizeof(login_status),0); // //receiving from server that login is successful or not
if(strcmp(login_status,"1")==0)
{
printf("login successfully 1\n");
//while(1);// doing other job here
return 1;
}
else if(strcmp(login_status,"0")==0)
{
printf("Wrong Username And/Or Password\nPress:\n__1)__To Enter Again | __2)__To Quit");
scanf("%d",&choice);
switch(choice)
{
case 1:
send(sockfd,"1", 2, 0);// sending that user want to login again
login(sockfd);
break;
case 2:
send(sockfd,"0",2,0);// sending that user want to stop
return 0;
//TODO default case
}
}
//break;//case 2 ends
}


int main(int argc, char *argv[])
{
char fname[50], s[INET6_ADDRSTRLEN], buf[MAXDATASIZE], username[50], password[50], registerStatus[2], login_status[2];
int sockfd, numbytes,fp,i,rv, choice,iflogin=0;

struct addrinfo hints, *servinfo, *p;

if(argc != 2)
{
fprintf(stderr,"usage: client hostname\n");
exit(1);
}

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;

if((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0)
{
fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(rv));
return 1;
}

//lopp through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next)
{
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
perror("client: socket");
continue;
}

if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
close(sockfd);
perror("client: connect");
continue;
}
break;
}

if(p ==NULL)
{
fprintf(stderr,"client: failed to connect\n");
return 2;
}

inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s);
printf("client : connecting to %s\n", s);

freeaddrinfo(servinfo); // all done with this structure





**////////////////////////// Here problem /////////////////////////**Code is continuous just to show you that problem is here.


////////////////////////// Here problem /////////////////////////
////////////////////////// Here problem /////////////////////////
////////////////////////// Here problem /////////////////////////


printf("\n----------------Menu-------------------------\n1.Register\n2.Log in\n");
scanf("%d",&i); //here i am asking user whether to register or login and while running i choose to register
int status_value;

if(i==1)// I am going to enter in this loop
{
send(sockfd,"1", 2, 0);//sending server that user want to register - work fine
printf("1\n");//work fine
status_value = registerYourself(sockfd);//this function ask me to register ang return 1 for success which is happening when I am running this code as:
if(status_value == 1)
{
printf("Logged in successful inside case 1\n"); // this prints
iflogin = 1;
printf("HERE 1-----------------\n");//this prints
printf("HERE 1-----------------\n");//this prints
}
else //not get in this -obvious
{
printf("Bye!!!");
printf("HERE 1!!!!!!!!!!!!!\n");
}
}
if(i==2)// also dont go in this loop - obvious
{
printf("Inside case 2");
send(sockfd,"2", 2, 0); //sending server that user want to login
//status_value = login(sockfd);
if(status_value == 1)
{
printf("Logged in successful inside case 2\n");
iflogin = 1;
}
else {
printf("Bye!!!");
}

}

//fflush(stdout);
//fflush(stdin);
//fflush(stderr);

// now some mytic thing is happening. this is not get printed and programmed get blocked [dont get stopped] just get blocked
//if I commented the last while(1) [in the end] loop then everything works fine
//if I commented the last while(1) and uncomment the sleep(5) statement t'outside here get printed after 5 seconds means after the sleep statement'
//I have also tried to flush - but this shit is not flushing
//pls tell me what is happening
printf("Outside here");
printf("Outside here");
printf("Outside here");
//sleep(5);
if(iflogin==1)
{
printf("Logged in");
}
else
{
printf("Final Bye");
}
while(1); //doing other job
close(sockfd);

return 0;
}


output- showing blocked state of the code in the end run with while(1) as explained in the problem
output- showing blocked state of the code in the end run with while(1) as explained in the problem

Answer

The line is not printed because printf() to standard output is line-buffered by default if standard output is a terminal (block buffered otherwise). Try:

printf("Outside here\n");

or add

fflush(stdout);

after the printf() statements. (EDIT) However, fflush(stdout) is not guaranteed to work because implementations are permitted to drop partial lines to stdout (partial means not terminated by \n). To be on the safe (portable) side, always terminate lines written to stdout with \n. See C99 7.19.2 paragraph 2:

A text stream is an ordered sequence of characters composed into lines, each line consisting of zero or more characters plus a terminating new-line character. Whether the last line requires a terminating new-line character is implementation-defined. [...]

Comments