Функция чтения со стороны Clinet возвращает случайные символы в конце сообщения (клиент-сервер TCP с использованием сокетов) - PullRequest
0 голосов
/ 06 января 2019

Практика сетевого программирования на C: я пишу простое клиент-серверное приложение TCP, которое должно отправлять сообщение (в отдельном потоке для каждого клиента) в виде строки с сервера на клиент и печатать сообщение на на стороне клиента (последняя на этом станет консольным магазином приложений). Сначала я отправляю размер сообщения, а затем само сообщение с использованием сокетов, функция write(). Сторона сервера:

void answer(void *arg) {
    struct thData tdL; 
    tdL= *((struct thData*)arg);

    // Welcome message
    char *initMsgToClient;
    getInitialMessage(&initMsgToClient);
    int len_initMsgToClient = strlen(initMsgToClient);

    // Returning message to client
    if ( write (tdL.cl, &len_initMsgToClient, sizeof(int)) <= 0 ) {
         printf("[Thread %d] ",tdL.idThread);
         perror ("[Thread] Error at write(): len_initMsgToClient to client.\n");
    }
    if (write (tdL.cl, initMsgToClient, len_initMsgToClient) <= 0) {
         printf("[Thread %d] ",tdL.idThread);
         perror ("[Thread]Error at write(): initMsgToClient to client.\n");
    }
    else
        printf ("[Thread %d] Message was sent with success.\n",tdL.idThread);

}

void getInitialMessage(char **paramMessage) {
    char *resultMessage = "Welcome to Console Shopper!";
    *paramMessage = resultMessage; 
}

И на стороне клиента я сначала читаю размер и само сообщение и печатаю его, но каждый раз, когда я запускаю ./client, я получаю разные произвольные символы в конце сообщения. Клиентская сторона:

char welcomeMessageFromServer[512];
int lenWelcomeMsg;
// Reading size of first mesage: lenWelcomeMsg
if (read(sd, &lenWelcomeMsg, sizeof(int)) < 0) {
    perror ("[client] Error reading len welcome message from server.\n");
}
// Reading initial message from server: welcomeMessageFromServer
if (read(sd, welcomeMessageFromServer, lenWelcomeMsg) < 0) {
    perror ("[client] Error reading welcome message from server.\n");
    return errno;
}
printf("%s",welcomeMessageFromServer);
printf("\n");

Для простоты я не добавил код для обработки сокетов и потоков, большая часть которого приведена в учебнике, поэтому он должен быть правильным. Я почти уверен, что делаю что-то не так с размером отправляемого / получаемого сообщения. Мой вывод с несколькими прогонами для ./client:

Welcome to Console Shopper!
Welcome to Console Shopper!�
Welcome to Console Shopper!������i0  
Welcome to Console Shopper!������UF+:  

В некоторых случаях это получается правильно. Что я должен исправить, чтобы все время получать правильное сообщение?

1 Ответ

0 голосов
/ 06 января 2019
// Reading initial message from server: welcomeMessageFromServer
if (read(sd, welcomeMessageFromServer, lenWelcomeMsg) < 0) {
    perror ("[client] Error reading welcome message from server.\n");
    return errno;
}
printf("%s",welcomeMessageFromServer);

У вас есть две проблемы здесь:

  1. Спецификатор формата %s предназначен только для строк в стиле C. Чтобы сделать ваше полученное сообщение строкой в ​​стиле C, вам необходимо положить завершающий нулевой байт на его конец.

  2. Функция read не гарантирует получение всех запрошенных байтов. Вам нужно проверить возвращаемое значение и вызвать его снова, если вы не получили полное сообщение.

Попробуйте использовать такую ​​функцию:

ssize_t readAll (int fd, void *vbuf, size_t count)
{
     char *buf = (char *) vbuf;
     ssize_t read_so_far = 0;
     while (count > 0)
     {
         ssize_t ret = read(fd, buf, count);
         if (ret < 0)
             return ret;
         if (ret == 0)
             return read_so_far;
         count -= ret;
         read_so_far += ret;
         buf += ret;
     }
     return read_so_far;
}

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

// Reading initial message from server: welcomeMessageFromServer
if (readAll(sd, welcomeMessageFromServer, lenWelcomeMsg) != lenWelcomeMsg) {
    perror ("[client] Error reading welcome message from server.\n");
    return errno;
}
welcoemMessageFromServer[lenWelcomeMsg] = 0;
printf("%s",welcomeMessageFromServer);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...