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?

Foi útil?

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 ...

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top