Cliente/servidor: Inteiro sempre recebido como 1 (programação C)
Pergunta
Estou construindo um cliente e um programa de servidor que trocam dados pelo TCP e estou tendo problemas para enviar uma confirmação ACK do servidor de volta ao cliente quando uma operação é bem-sucedida. Consegui enviar uma estrutura com vários membros do cliente para o servidor, então o servidor deve responder enviando um número inteiro confirmando o ID da estrutura de volta ao cliente.
No server.c, tenho esta função:
int sendACK(int socket, int ack_int){
int com_result;
int ACK = htonl(ack_int);
printf("\n\tSending ACK with value: %i", ack_int);
com_result = send(socket, &ACK, sizeof(ACK), 0);
if (com_result == -1) {
perror("\n\t[ERROR] Send ACK");
return 0;
}
return 1;
}
Esta função é chamada por outra função no servidor.c como esta:
int ACK = myStruct->ID;
sendACK(socket, ACK);
Então, se eu acabei de receber uma estrutura com ID: 2, a saída será:
Enviando ACK com valor: 2
Em client.c, eu recebo o ACK assim:
int ACK = 0;
data_size = sizeof(myStruct.ID);
com_result = read(client_socket, &ACK, data_size);
ACK = ntohl(ACK);
if (com_result == -1) {
perror("\n\t[ERROR] Read");
} else {
printf("\n\tRecieved %i of %i bytes", com_result, data_size);
if (ACK != myStruct.ID) {
printf("\n\t[ERROR] Invalid ACK (%i).", ACK);
}
}
Mas o ACK é sempre recebido com um valor de 1, então a saída do cliente é:
Recebido 4 de 4 bytes
Erro] ACK inválido (1).
Por que o número inteiro não foi recebido com um valor de 2, e como posso consertar isso?
Solução
Provavelmente, esse não é o problema, mas acredito que a segunda linha em seu snippet client.c abaixo deve ter tamanho de (ACK).
int ACK = 0;
data_size = sizeof(ACK); // was: sizeof(myStruct.ID);
com_result = read(client_socket, &ACK, data_size);
ACK = ntohl(ACK);
Além disso, dependendo do seu fluxo de dados, é possível que você esteja realmente lendo corretamente e a ACK seja a resposta de um pacote que você enviou anteriormente?
Outras dicas
Você nunca deve enviar valores inteiros como esse, precisa prestar mais atenção à serialização. Isso pode falhar se, por exemplo, o sizeof (int)
é diferente na máquina de envio do recebimento, caso em que você lerá o número incorreto de bytes.
É melhor tomar mais cuidados e serializar campos um byte de cada vez.
Para depurar, você pode usar Wireshark. Executar Wireshark e defina suas opções para ouvir a porta necessária. Você verá o que foi realmente enviado dentro do pacote pela rede. Isso permitirá que você entenda se o problema está com o servidor, o cliente ou ambos.
Não consigo descobrir nada de errado com o código que você colou acima. Eu sugiro sair do Wireshark, ou outro programa de rastreamento de soquete e olhar para os bits no fio.
Eu verificaria se o código principal do remetente/receptor está lidando com a quantidade correta de dados.
Se o seu remetente enviar 20 bytes seguidos por um ACK de quatro bytes, mas o receptor lê apenas 16 antes de tentar ler o ACK, você poderá ter esse tipo de problema.
Se você estiver enviando dados de comprimento variável (por exemplo, com um prefixo bytecount), uma confusão comum sobre se o bytecount transmitido inclui realmente os bytes adicionais necessários para enviar a contagem de bytes ...