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:

我目前拥有的。

服务器.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;

}

客户端.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);  
}
4

2 回答 2

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...>
于 2013-11-14T15:31:54.320 回答
1

scanf不使用用户选择后点击的换行符。但是fgets立即可以,仅此而已。正确的解决方案是停止使用scanf(这是任何使用scanf, IMO 的程序的正确解决方案)。但是在格式字符串中添加空格可能更简单:

scanf( "%d " ... )
于 2013-11-14T15:00:05.090 回答