htonl/ntohl не правильное значение для второй команды?

Изменить: я, честно говоря, понятия не имею, где происходит ошибка, поэтому я просто добавлю большую часть соответствующего кода, не уверен, поможет ли это

так что в основном у меня есть два основных серверных и клиентских процесса. Пользователь указывает команду, клиентский процесс затем отправляет длину сообщения на сервер, сервер выполняет команду и отправляет обратно длину сообщения ответа.

Это хорошо работает для первой команды (я пробовал две команды ls -la подряд), значение равно 1028 для первой команды (правильное значение) и неправильно 1685223288(для клиента) для второй команды

Запись выполняется с помощью следующего кода:

server_handler() {
char str[5000];
char * token = NULL;
unsigned long totalSize = 0;
str[0] = "\0";
totalSize = htonl(totalSize); // Correct size already calculate
if((result = write(clientFD, (char *) &totalSize, sizeof(totalSize)) < 0))
{
     printf("Failed sending size to client\n");
     exit(-1);
}
//Here the server starts sending the results to the client
token = strtok(str, "\n"); // str array contains the results
while(token != NULL)
{
     token[strlen(token)] = '\n';
     write(clientFD, token, strlen(token));
     token = strtok(NULL, "\n);
}

Чтение выполняется в клиентском процессе следующим образом:

static void handle_reply() 
{
char * revBuf = 0;
unsigned long int bytesRead = 0;
unsigned long bufferlen = 0;
while(1) 
{
    result = read(socketFD, (char *) &bufferlen, sizeof(bufferlen));
    bufferlen = ntohl(bufferlen);
    recvBuf = malloc(bufferlen);
   //Here client starts reading results
    while(bytesread < bufferlen)
    {
        result = read(socketFD, recvBuf, bufferlen);
        printf("recvBuf: %s\n", recvBuf);
        bytesRead = strlen(recvBuf) + bytesRead;
    }
    free(recvBuf);
    bufferlen = 0;
   client_handler(); //calls Function that asks for new command
}
}

Мой вопрос: почему я получаю неправильные значения команд после первой? Я проверил, что totalSize имеет правильное значение на стороне сервера в обоих случаях при печати. Что-то должно быть не так в записи / чтении?

Я также напечатал htonl(totalSize) на сервере, и это 67371008. Однако значение, полученное на стороне клиента, составляет 2021093988 до ntohl.

2 ответа

Решение

Следующий код не будет работать правильно, потому что вы звоните strlen снова после изменения строки.

token = strtok(str, "\n");
while(token != NULL)
{
    token[strlen(token)] = '\n';
    write(clientFD, token, strlen(token));
    token = strtok(NULL, "\n");
}

Для иллюстрации предположим, что str изначально "hello\nworld\n", В гексе это

 68 65 6c 6c 6f 0A 77 6f 72 6c 64 0A 00
                ^---- the first newline

После strtok это будет

 68 65 6c 6c 6f 00 77 6f 72 6c 64 0A 00
                ^---- strtok changed it to a NUL

После линии token[strlen(token)] = '\n' это будет

 68 65 6c 6c 6f 0A 77 6f 72 6c 64 0A 00
                ^---- you changed it back to a newline

так что теперь strlen в write вернет 12, так что write отправит 12 байтов, а не 6, как вы ожидаете. Это можно исправить, позвонив strlen однажды, вот так

token = strtok(str, "\n");
while(token != NULL)
{
    size_t length = strlen(token);
    token[length] = '\n';
    write(clientFD, token, length);
    token = strtok(NULL, "\n");
}

htonl и ntohl - это 32 бита...

  uint32_t htonl(uint32_t hostlong);
  uint32_t ntohl(uint32_t netlong);

Посмотрите, что происходит с большими целыми числами в этой программе с 64-битной системой.

#include <stdio.h>

int main(int argc, char** arg)
{
  unsigned long bufferlen = 0;
  unsigned long totalSize = 1024;
  sscanf(arg[1],"%lld",&totalSize);
  printf("%lld  %llx\n", totalSize,totalSize);

  totalSize = htonl(totalSize); // 32 <-> 64bits .
  bufferlen = ntohl(totalSize);

  printf("%lld %llx %lld %llx\n", totalSize,totalSize,bufferlen,bufferlen);

}

тестирование это:

./test 111111111111111
111111111111111  650e124ef1c7
-940487150 ffffffffc7f14e12 307163591 124ef1c7
Другие вопросы по тегам