2012-04-15 108 views
-4

我正在用注册登录系统制作服务器聊天应用程序。在运行客户端代码时:我首先选择注册,然后在成功注册后,客户端代码提示我登录。然后我登录,它工作正常。我已经在客户端代码的if else块中实现了这两件事。在此之后,我正在做一些事情,我遇到了我的C生活中最具吸引力的错误之一。这里是我的源代码,在该代码中我标记了有错误的区域(在main函数的末尾)并且还提到了那里的问题(问题的代码定义很容易)。
我也发布代码后的输出。运行时深奥的C程序行为 - 代码没有按顺序运行

#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 输出 - 在与而端预演阻断代码的状态(1)如在问题

+0

当您在调试器中逐句通过代码时,您看到了什么? (你是什么意思,你没有通过代码步骤?这不是一个可选的步骤) – abelenky 2012-04-15 18:45:37

回答

2

行不打印,因为printf()到标准输出解释是行缓冲由如果标准输出是一个终端(否则缓冲块)。尝试:

printf("Outside here\n"); 

printf()语句之后添加

fflush(stdout); 

。 (编辑)但是,fflush(stdout)不能保证工作,因为允许实现将部分行删除到标准输出(部分意味着不被\n终止)。要在安全(便携式)方面,总是用\n终止写入标准输出的行。见C99 7.19.2第2段:

文本流是由成 行字符的有序序列,另外,每个行包括零个或多个字符的 终止换行字符。最后一行是否需要 终止换行字符是实现定义的。 [...]

+0

我已经使用fflushn但没有发生,但在你的建议后,我试过\ n和它的工作,但你能告诉我为什么? – 2012-04-15 18:50:05

+0

编辑,以反映为什么'fflush()'不能保证在这种情况下工作。 – 2012-04-15 19:07:08

+0

我明白,如果我不放\ n那么流将增加到所有printf语句,但在所有printf语句之后它必须被打印成一行。那么为什么它不打印。 – 2012-04-15 19:10:27