2013-11-14 88 views
0

我試圖建立客戶端和服務器之間的連接,當它成功時, 將顯示一個菜單屏幕,提示用戶他是否想要 1)輸入消息 2)退出程序。套接字編程獲取輸入

我所面臨的問題是,當我在一個鍵,它會返回我下面

客戶 輸出所示(它只是將回頭率「我把你味精,每當我進入‘1’,而不具有輸出用戶輸入的消息第一,直到我按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 

服務器

Here is the msg: 

    Here is the msg: 

    Here is the msg: 

我有什麼目前。

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); 
} 
+1

仔細閱讀該男子-頁閱讀' '''write',並且知道至少對於套接字來說,這兩個函數並不一定按照它們所告知的讀取/寫入儘可能多的字節,而是很少。因此,圍繞此類呼叫進行計數,直到收到/發送所有數據都是一個好主意,而不是說必不可少。 – alk

+0

OT:'read' /'write'返回'ssize_t'不是'int'。 – alk

+0

感謝您的意見@alk – user3429531

回答

1

scanf不消耗用戶進行選擇後擊中換行符。但fgets立即做,並沒有別的。正確的解決方案是停止使用scanf(這是任何使用scanf,IMO的程序的正確解決方案)。但是,它可能是簡單的空間添加到格式字符串:

scanf("%d " ...) 
+0

感謝您的幫助 – user3429531

2

爲什麼fgets()無法讀取輸入緩衝區的原因是你scanf留在輸入緩衝區的新行字符。

因此,您的fgets將在調用它後很快返回。在client.c

代碼應作如下修改:

<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...> 

此外,在server.c代碼應作如下修改:

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