отправить() перед recv()

#c #sockets #winapi #recv

#c #сокеты #winapi #recv

Вопрос:

у меня есть два проекта: один — клиент, а другой — сервер. допустим, сервер должен отправлять клиенту 2 сообщения одно за другим. клиентский код выглядит следующим образом:

 while(1)
{
      recv(acceptedStr, socket);
      printf("%sn, acceptedStr);
      *other code lines*
}
 

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

 while(1)
    {
          send(socket, "First String");
          send(socket, "Second String");
          *other code lines*
     }
 

если для второй отправки нет ТАЙМ-аута, получит ли recv клиента «Вторую строку»? или он должен убедиться, что он находится в recv перед отправкой сервером?

Комментарии:

1. Вы ожидаете увидеть a n после каждой из отправленных строк? Это не гарантируется. При TCP-соединении вы можете получать данные с помощью одного recv или десяти. Обеспечивается только порядок. Не границы между отдельными send вызовами. Если вы используете UDP, то граница каждой дейтаграммы фиксирована, но вы можете получать их в другом порядке.

2. Ваши аргументы вызова send и recv неверны.

3. Вероятно, вам нужен какой-то цикл событий . Рассматривали ли вы возможность использования libevent или GTK ?

Ответ №1:

Нет, принимающая сторона не должна иметь recv активный для send работы.

После установления соединения данные буферизуются сетевым стеком операционной системы. И recv завершится успешно после поступления данных и send завершится успешно, если данные были доставлены в сетевой стек получателя.

Ответ №2:

Ответ на ваш вопрос

Да, этого достаточно, и ваш код будет работать. Но если вы хотите расширить его больше, или если сервер и клиент должны быть синхронизированы все время, продолжайте чтение.

Синхронизация сервера и клиента

Прочитайте это, если вы хотите синхронные операции сервера и клиента.

Я ранее работал с send и recv, и я бы посоветовал вам одну вещь: вы всегда чередуете recv и send дополнительными способами. В качестве примера

Сервер:

 send()
recv()
send()
.
.
.
 

Клиент:

 recv()
send()
recv()
.
.
.
 

Обычно отслеживать это утомительно. (Я думаю, что вызывается обратная отправка от объекта на recv ack ).

Но в какой-то момент вы хотели бы повернуть поток событий. Для этого вы можете просто отправить и восстановить некоторые случайные данные.

Ранее я написал оболочку вокруг send и recv для своего проекта. Не стесняйтесь проверить это: https://github.com/ArenaGrenade/Simple-FTP-Server/blob/main/utils.cpp . (Это довольно хорошо документировано, поэтому, даже если вы не поняли мое объяснение, вы бы поняли то, что в коде.)

Дайте мне знать, если вы поняли, отметив мое как ответ. Рад помочь! Если у вас есть сомнения, просто прокомментируйте ниже. 🙂

Комментарии:

1. Где ваш комментарий? @alk

2. Я удалил его. Я не ответил на вопрос.

3. Нет проблем! Сделайте upvote, если вы считаете это правильным. Спасибо.

Ответ №3:

Клиент действительно получает Second String , но он работает не так, как вы думаете.

Я создал клиент и сервер с помощью двух официальных образцов: полного кода клиента Winsock и полного кода сервера Winsock

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

Когда я пытаюсь отправить данные два раза подряд, клиент получит следующее содержимое:

введите описание изображения здесь

введите описание изображения здесь

Вы можете видеть, что клиент действительно получает Second String , но поскольку вы продолжаете отправлять эти два данных, это вызовет проблемы на картинке.

Поскольку данные отправляются непрерывно, клиент также будет получать данные, отправленные несколько раз за один раз, и сохранять их в один и тот же буфер, хотя отображается только его часть (поскольку она усекается на ‘ 0’), но это видно по размеру буферачто данные, отправленные несколько раз, принимаются одновременно.И содержимое, полученное позже, будет непредсказуемым