2017-02-02 4 views
0

У меня есть приложение для чата для командной строки, но я не могу понять, как отобразить приглашение «Ввести сообщение:» для каждой записи сообщения. Это очень простая проблема, но многопоточность и отношения клиент/сервер меня отбрасывают.Показать командную строку с помощью fgets в приложении с многопоточным чатом

Клиент код сторона:

#define PORT 12000 
#define BUFFER 4096 

void * receive(void * socket) { 
    int socket_fd, response; 
    char buffer[BUFFER]; 
    socket_fd = (int) socket; 
    while(true) { 
     response = recvfrom(socket_fd, buffer, BUFFER, 0, NULL, NULL); 
     if (response) { 
      printf("Server: %s", buffer); 
     } 
    } 
} 

int main(int argc, char**argv) { 
    struct sockaddr_in address, cl_addr; 
    char * server_address; 
    int socket_fd, response; 
    char buffer[BUFFER]; 
    pthread_t thread; 

    if (argc < 2) { 
     printf("Usage: client [IP Address]\n"); 
     exit(1); 
    } 

    server_address = argv[1]; 
    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = inet_addr(server_address); 
    address.sin_port = PORT; 
    socket_fd = socket(AF_INET, SOCK_STREAM, 0); 

    response = connect(socket_fd, (struct sockaddr *) &address, sizeof(address)); 
    if (response < 0) { 
     printf("Failed to connect\n"); 
     exit(1); 
    } 

    printf("Connected\n"); 

    // Create new thread to receive messages 
    pthread_create(&thread, NULL, receive, (void *) socket_fd); 

    // Get message from stdin and send to server 
    printf("Enter a message: "); 
    while (fgets(buffer, BUFFER, stdin) != NULL) { 
     sendto(socket_fd, buffer, BUFFER, 0, (struct sockaddr *) &address, sizeof(address)); 
    } 

    close(socket_fd); 
    pthread_exit(NULL); 
    return 0; 
} 

Вопрос заключается в том, что «Введите сообщение:» отображается только один раз. Я попытался добавить его внутри цикла while (fgets), который успешно помещает запрос в каждую строку, которую пишет клиент, но когда сервер отправляет что-то, он отбрасывается.

Connected 
Enter a message: foo 
Enter a message: bar 
Enter a message: Server: foo 
Server: bar 

Я пытался добавить новые строки в разных местах и ​​при добавлении другой строки после функции receive, но независимо от того, что я делаю, не всегда какой-то крайний случай, который портит вещи. Есть ли способ просто дать fgets запрос по умолчанию или что-то еще? Я потратил слишком много времени на то, что должно быть так просто.

ответ

1

Есть ли способ, чтобы просто дать fgets сообщение по умолчанию или что-то еще?

Не то, что я знаю, если вы не хотите, чтобы начать использовать библиотеку как ncurses сделать более продвинутое управление терминалом (и для программы игрушек, вы, вероятно, нет).

Что вы можете сделать вместо этого:

  1. Вызов fflush(stdout); сразу после printf("Enter a message: "); вызова, чтобы заставить текст в строке, чтобы отображаться сразу (а не только после того, как следующий символ новой строки печатается).

  2. Поместите символ возврата каретки в начало вашего сервера-printf(), например. printf("\rServer: %s\n", buffer); Это переместит текстовый курсор терминала в начало строки, так что текст server-printf() будет перезаписывать приглашение, а не добавлять к нему. (Обратите внимание, что если ваш серверный текст недостаточно длинный, вам может потребоваться добавить дополнительные места в конец, чтобы убедиться, что текст вашего приглашения перезаписан)

Смежные вопросы