Boost.Asio синхронное общение - PullRequest
0 голосов
/ 10 августа 2009

У меня проблема с использованием asio. Мое клиент-серверное приложение требует только синхронной связи. Итак, используя примеры для синхронизации с домашней страницы буста, я настроил две процедуры для отправки и получения данных. Их код выглядит следующим образом:

void vReceive(tcp::socket & socket, std::string & szDest){
    char szTmp_Buf [BUF_LEN + 1];
    szDest = "";
    std::cout << "Entering vReceive . . ." << std::endl;

    for (;;){
      char szBuf [BUF_LEN];
      boost::system::error_code error;
      uInt uiBytes_Recv = socket.read_some(boost::asio::buffer(szBuf), error);
      std::cout << " Read " << uiBytes_Recv << " bytes" << std::endl;
      if (error == boost::asio::error::eof)
         break; // Connection closed cleanly by peer.
      else if (error)
         throw boost::system::system_error(error); // Some other error.

      memcpy((void*) szTmp_Buf, (void*) szBuf, uiBytes_Recv );
      szTmp_Buf[ uiBytes_Recv ] = '\0';
      szDest += szTmp_Buf;
      };
      std::cout << "Received" << szDest << std::endl;
      std::cout << "Leaving vReceive . . ." << std::endl << std::endl;
   };

void vSend(tcp::socket & socket, std::string & szSrc){
    std::cout << "Entering vSend . . . " << std::endl;
    std::cout << "Sending " << szSrc << std::endl;
    boost::system::error_code ignored_error;
    boost::asio::write(socket, boost::asio::buffer(szSrc), boost::asio::transfer_all(), ignored_error);
    std::cout << "Leaving vSend . . . " << std::endl << std::endl;
    };

Эти процедуры являются просто оболочками для строк кода, извлеченных из примеров надстройки.

В моих тестовых приложениях клиент вызывает

std::string szDate;
vReceive(socket, szDate);
vSend(socket, std::string("Chop Suey!") );
vReceive(socket, szDate);
vSend(socket, std::string("Halo"));

и сервер звонит

std::string message = make_daytime_string();
std::string szReceived;
vSend(socket, message);
vReceive(socket, szReceived);
vSend(socket, message);
vReceive(socket, szReceived);

только для проверки работоспособности. Проблема в том, что оба приложения замерзают после первого обмена информацией, как я изобразил на следующем рисунке . Кажется, что процедура vReceive () на стороне клиента не завершается, в то время как vSend () заканчивается на стороне сервера. Итак, у кого-нибудь есть идеи, что может быть не так?

На тот случай, если кто-то захочет воспроизвести проблему, я загрузил полные исходники на тот же сервер, где картинка находится в файле asio_problem.rar (у меня может быть одна гиперссылка на пост в качестве нового участника).

Спасибо всем заранее, Daniel.

1 Ответ

1 голос
/ 17 ноября 2009

Я думаю, что ваша проблема лежит здесь:

for (;;){
  /* snipped */

  if (error == boost::asio::error::eof)
     break; // Connection closed cleanly by peer.
  else if (error)
     throw boost::system::system_error(error); // Some other error.

  /* snipped */
}

Вы выполняете цикл бесконечно, пока не закроется соединение (единственный способ выйти из цикла - это получение ошибки EOF из сокета), но vSend никогда не закрывает сокет. Это означает, что vReceive в вашем клиенте будет ждать вечно, всегда ожидая больше данных. Помещение socket.close() в vSend должно хорошо сработать.

Конечно, это означает, что вашему клиенту и серверу нужно будет заново открывать сокет после каждого соответствующего вызова vReceive и vSend. Если это нежелательно, я рекомендую использовать другие средства отправителя, уведомляющего получателя о том, что больше не будет отправлено данных.

Я не уверен, есть ли у вас какие-либо ограничения в отношении данных, передаваемых по проводной связи, но либо отправляю значение «длина данных» в начале вашего сообщения, либо какое-то значение «конец данных» для стража в конце вы получите хороший, чистый индикатор того, когда прекратить прослушивать больше данных.

Этот подход имеет дополнительные преимущества, так как дает вам причину использовать функциональность read_until (или аналогичную) ASIO для обработки логики ожидания конца данных для вас.

...