У меня есть сервер и клиентская программа (оба работают на одной машине). Клиент может отправить структуру на сервер с такими элементами, как «ID», «размер» и т. д. Затем я хотел бы, чтобы сервер отправил идентификатор-член (только целое число) обратно клиенту в качестве ACK для проверки , но я просто не могу понять это, несмотря на то, что могу без проблем отправить структуру.
Вот код из server.c:
/* having just recieved the struct */
int ACK_ID = struct_buffer->message_ID;
result = send(CLIENT_socket, &ACK_ID, sizeof(int), 0);
if (result == -1) {
close(SERVER_socket);
printf("\n\t[ERROR] Failed to send ACK.\n");
exit(EXIT_FAILURE);
}
Вот код из client.c:
// Recieve ACK from server
int ACK_ID;
com_result = read(CLIENT_socket, &ACK_ID, sizeof(int), 0);
if ((com_result == -1) || (ACK_ID != metablocks[index].message_ID)) {
printf("\n\t[ERROR] Failed to send metadata. ACK: %i\n", ACK_ID);
}
Когда я пытаюсь запустить это, я получаю следующий вывод из client.c:
[ОШИБКА] Не удалось отправить метаданные. ПОДТВЕРЖДЕНИЕ: 14
И, конечно же, сервер сообщает мне, что ему не удалось отправить ACK. Значение целого числа ID, которое я пытаюсь отправить, должно быть 1, но оно получено как 14. Что я здесь делаю неправильно?
Обновление
Итак, я просто попробовал то, что предложил г-н Шоули, и получил следующее сообщение об ошибке:
Частичное чтение: неопределенная ошибка: 0
Сначала попробовал именно то, что он написал, но потом заметил, что код сравнивает com_result
с sizeof(int)
. Поэтому я предположил, что это опечатка, и попытался заменить com_result
на переменную ACK_ID
в сравнении. Тот же результат.
Обновление 2
Только что добавил perror() на сервер при сбое и получил следующее сообщение об ошибке:
Неверный файловый дескриптор
Я использую для этой операции тот же сокет, что и при получении структуры. Вот расширенный пример кода из server.c:
// Recieve connection
CLIENT_socket = accept(SERVER_socket, (struct sockaddr *)&CLIENT_address, &CLIENT_address_length);
if (CLIENT_socket == -1) {
close(SERVER_socket);
printf("\n\t[ERROR] Failed to accept client connection.\n");
exit(EXIT_FAILURE);
}
printf("\n\tClient connected!\n");
int data_size;
// Read meta data from connection
data_size = sizeof(struct msg_meta);
result = read(CLIENT_socket, &meta_buffer_char, data_size, 0);
meta_buffer = (struct msg_meta *) meta_buffer_char;
if (result == -1) {
close(SERVER_socket);
printf("\n\t[ERROR] Failed to read from connection.\n");
perror("\n\tRead");
exit(EXIT_FAILURE);
} else if (result > 0) {
printf("\n\tMessage recieved.\n");
printf("\n");
}
// Send ACK back to client
int ACK_ID = meta_buffer->message_ID;
result = send(CLIENT_socket, &ACK_ID, sizeof(int), 0);
if (result == -1) {
printf("\n\t[ERROR] Failed to send ACK.");
perror("\n\tSend");
printf("\n");
close(SERVER_socket);
exit(EXIT_FAILURE);
}
// Close sockets
close(SERVER_socket);
close(CLIENT_socket);
htonl
иntohl
при отправке и получении (соответственно) int, чтобы убедиться, что он имеет правильный порядок байтов. - person outis   schedule 15.11.2009perror
на стороне сервера. (Кстати, частичное чтение довольно странно, если сервер не может отправить ACK!) - person Andomar   schedule 15.11.2009FIN
. Закрытие сокета на стороне сервера приведет к получению нулевых байтов на стороне клиента. Я знал, что была причина, по которой я так давно обернул весь свой TCP-код в библиотеку;) - person D.Shawley   schedule 15.11.2009perror
в первую очередь. Если вы вызовете его послеclose
илиprintf
, он сообщит, чтоprintf
выполнено успешно. - person Andomar   schedule 16.11.2009