Вопрос или проблема
Я пытаюсь создать клон redis. Я настроил простой TCP-сервер, который слушает запросы от клиента и обрабатывает их.
//начало фрагмента
if (server_fd == -1) {
printf("Ошибка создания сокета: %s...\n", strerror(errno));
return 1;
}
int reuse = 1;
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
printf("Не удалось установить SO_REUSEADDR: %s \n", strerror(errno));
return 1;
}
struct sockaddr_in serv_addr = { .sin_family = AF_INET ,
.sin_port = htons(6379),
.sin_addr = { htonl(INADDR_ANY) },
};
if (bind(server_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) != 0) {
printf("Ошибка привязки: %s \n", strerror(errno));
return 1;
}
int connection_backlog = 5;
if (listen(server_fd, connection_backlog) != 0) {
printf("Ошибка прослушивания: %s \n", strerror(errno));
return 1;
}
printf("Ожидание подключения клиента...\n");
client_addr_len = sizeof(client_addr);
while (1) {
client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &client_addr_len);
if (client_fd == -1) {
printf("Ошибка приема: %s \n", strerror(errno));
return 1;
}
child_pid = fork();
switch (child_pid) {
case -1:
printf("Ошибка форка: %s \n", strerror(errno));
return 1;
case 0:
// дочерний процесс
close(server_fd);
handle_client(client_fd);
//конец фрагмента
//начало фрагмента
ssize_t bytes_read;
char client_request[1024];
char *command;
bytes_read = read(client_fd, client_request, sizeof(client_request));
if (bytes_read == -1) {
printf("Ошибка чтения: %s \n", strerror(errno));
return;
}
if (bytes_read < 2) {
handle_send_usage(client_fd);
return;
}
extract_command(client_request, command);
У меня возникла проблема с извлечением команды. Когда я рассматриваю точные байты client_request
в строке, содержащей extract_command
, я вижу, что к оригинальному запросу добавляются лишние FF.
gef➤ x/gx client_request
0xffffffffee98: 0x0000ffff474e4950
Пожалуйста, уточните, является ли это обычным поведением, или я что-то упустил?
Я использую
echo -n "PING" | nc localhost 6379
чтобы отправить запрос.
Ответ или решение
Ваша проблема с тем, что в массиве client_request
появляются лишние байты FF
, вероятнее всего, связана с тем, что вы не корректно обрабатываете данные, считываемые из сокета. Рассмотрим, в чем может быть проблема и как это исправить.
Когда вы вызываете функцию read()
, она считывает данные из сокета в буфер (client_request
), и переменная bytes_read
указывает на количество прочитанных байт. В вашем случае вы получаете байты и затем пытаетесь извлечь команду, однако не учитываете, что массив client_request
может быть не полностью инициализирован, особенно если не все байты в нем были заполнены.
Возможные причины проблемы:
-
Неинициализированный буфер: Если ваш
client_request
массив не инициализирован полностью до вызоваread()
, может быть, что его оставшаяся часть содержит мусор, включая значения0xFF
. -
Кодирование и операции с строками: Убедитесь, что вы правильно обрабатываете строки из буфера. Если вы не ставите нуль-терминатор в конец прочитанных данных, функции, работающие со строками, могут вести себя непредсказуемо.
-
Проблемы с длиной сообщения: Если
bytes_read
меньше размера вашего ожидаемого ввода, и вы не проверяете корректно, сколько байтов было прочитано, это может привести к попытке обработки лишних данных.
Возможные решения:
-
Инициализируйте буфер перед считыванием:
memset(client_request, 0, sizeof(client_request));
-
Убедитесь, что вы правильно завершаете строку нуль-терминатором после чтения:
client_request[bytes_read] = '\0'; // Завершите строку
-
Проверяйте, что
bytes_read
больше нуля:if (bytes_read <= 0) { printf("No data read or read failed.\n"); return; }
-
Исправьте функцию
extract_command
:
Ваша функцияextract_command
должна принимать корректный размер данных, чтобы избежать чтения за пределами фактических данных. Например:void extract_command(char *request, ssize_t length) { // Логика извлечения команды с учетом длины ... }
Пример исправленного кода:
ssize_t bytes_read;
char client_request[1024];
memset(client_request, 0, sizeof(client_request));
bytes_read = read(client_fd, client_request, sizeof(client_request) - 1); // Оставьте место для нуль-терминатора
if (bytes_read == -1) {
printf("Read failed: %s \n", strerror(errno));
return;
}
if (bytes_read < 2) {
handle_send_usage(client_fd);
return;
}
client_request[bytes_read] = '\0'; // Завершите строку
extract_command(client_request, bytes_read);
Это должно помочь устранить проблему с лишними FF
. Проверьте эти изменения и протестируйте ваш код снова. Успехов в разработке!