Модераторы: feodorv

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> баг asio? или баг TCP стека? 
V
    Опции темы
boostcoder
Дата 23.3.2011, 14:30 (ссылка)    | (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



всем доброго дня.

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

код клиента выполняет следующее:
1. выделение памяти у ОС в boost::shared_array.
2. сериализация.
3. копирование в shared_array.
4. boost::asio::async_write().
5. tcpdump показывает что данные ушли.
6. на приеме данные искажены.

лог tcpdump`a для пояснения формирования непонятных "фреймов":
строки сериализации содержащие подстроки servimpl - это то, что отправляется от клиента серверу.
строки сериализации содержащие подстроки type1 - это то, что отправляется от сервера клиенту.
user posted image
что за непонятные данные присутствующие кроме архивов сериализации - мне не известно.
в точке 1 показан пример когда архив разбивается. в точке 2 показана остальная часть архива. этот архив на принимающей стороне восстанавливается правильно. ошибки не возникает.

далее...
в точке 3 происходит разбиение очередного архива, остальная часть которого появляется только в точке 5.
т.е. это именно та итерация(348), на которой происходит искажение архива, и как следствие - ошибка десериализации.
user posted image

далее...
в точке 4 должен находится остаток архива разбитого в точке 3.
user posted image

вот та часть, в которой появляется остаток от архива разбитого в точке 3.
user posted image

какие мысли?

Это сообщение отредактировал(а) boostcoder - 8.4.2011, 00:57
PM WWW   Вверх
Daevaorn
Дата 23.3.2011, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

Репутация: нет
Всего: 70



Где код?
PM MAIL WWW   Вверх
boostcoder
Дата 23.3.2011, 15:13 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



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

Добавлено через 1 минуту и 35 секунд
я рассчитывал на то, что кто-то увидит знакомую ситуацию, и подскажет как решить.

зы
кстати, если между отправками данных поставить sleep на 1мс - то проблема решается полностью.
PM WWW   Вверх
boostcoder
Дата 23.3.2011, 15:58 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(boostcoder @  23.3.2011,  15:13 Найти цитируемый пост)
причину нужно искать в том коде, который добавляет к моим данным нечитаемые данные и разбивает мои данные на "фреймы".

кто-то знает кто может добавлять к моим данным нечитаемые данные и разбивать их на фреймы? это выполняет TCP стек? сетевая подсистема? просто не знаю как это называется...

Это сообщение отредактировал(а) boostcoder - 23.3.2011, 16:07
PM WWW   Вверх
boostcoder
Дата 24.3.2011, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



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


Присоединённый файл ( Кол-во скачиваний: 11 )
Присоединённый файл  asiotest.zip 2,75 Kb
PM WWW   Вверх
MAKCim
Дата 27.3.2011, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  23.3.2011,  15:58 Найти цитируемый пост)
это выполняет TCP стек?

фрагментация осуществляется на сетевом уровне
к данным "мусор" добавляться не может

вы точно уверены, что в сокет все записывается правильно?
вы сравнивали, что передается в async_write() и в send()?


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
marykone
Дата 27.3.2011, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2722
Регистрация: 2.5.2006
Где: Краснодар

Репутация: нет
Всего: 67



boostcoder, данные скорее всего искажены именно от отправителя.
На первый взгляд, именно так. копать... 
Если дальше копать то послушайте трафик wireshark, и выложите сюда. ну может конечно кто то и tcp дамп почитать смоежт я как то не.



--------------------
получил ответ, пометь вопрос как решенный (правый верхний угол вашей темы).

PM   Вверх
MAKCim
Дата 27.3.2011, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



по поводу задержки
если постоянно записывать данные, а читать с задержкой 1 мс, то данные будут накапливаться в буфере сокета ядра...хм, может тут проблема
версия ядра какая?


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
boostcoder
Дата 28.3.2011, 15:18 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  27.3.2011,  21:06 Найти цитируемый пост)
фрагментация осуществляется на сетевом уровне
к данным "мусор" добавляться не может

тот мусор что на скринах, показывает tcpdump. в мой код этот мусор не поступает.

Цитата(MAKCim @  27.3.2011,  21:06 Найти цитируемый пост)
вы точно уверены, что в сокет все записывается правильно?

насколько это возможно утверждать на приведенном коде - да. просто код реально мегапрост, чтоб где-то мог закрасться баг. если конечно это не баг asio. в чем сомневаюсь.. иначе данные портились бы не только в этом примере, но и в других приложениях.

Цитата(MAKCim @  27.3.2011,  21:06 Найти цитируемый пост)
вы сравнивали, что передается в async_write() и в send()? 

нет. а как это сделать? добавить в недры asio вывод?
или есть какой-то еще способ?

Цитата(marykone @  27.3.2011,  21:17 Найти цитируемый пост)
послушайте трафик wireshark, и выложите сюда.

сейчас сделаю.

Цитата(MAKCim @  27.3.2011,  21:43 Найти цитируемый пост)
если постоянно записывать данные, а читать с задержкой 1 мс, то данные будут накапливаться в буфере сокета ядра...хм, может тут проблема

эм.. помогает задержка при записи, а не при чтении.

Цитата(MAKCim @  27.3.2011,  21:43 Найти цитируемый пост)
версия ядра какая?

я проверял не только на линукс...

клиентский код запускаю на: 2.6.35-28-generic-pae
код сервера на: 2.6.35-25-generic-pae
PM WWW   Вверх
boostcoder
Дата 28.3.2011, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



логи.
сделал wireshark`ом на локальной стороне.
на сервере нет X`ов, я хз как там wireshark запускать.

зы
по логам, ничего не понял...


Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  logs.zip 76,38 Kb
PM WWW   Вверх
boostcoder
Дата 28.3.2011, 18:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



заново протестил еще раз на winXP/Win7/Linux.
баг воспроизводится всегда :(
тестил так:
Цитата

клиент | сервер | локально/удаленно
-------------------------------------
WinXP    WinXP    локально
WinXP    Linux    удаленно
Win7     Win7     локально
Win7     Linux    удаленно
Linux    Linux    локально
Linux    Linux    удаленно

PM WWW   Вверх
MAKCim
Дата 29.3.2011, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  28.3.2011,  15:18 Найти цитируемый пост)
насколько это возможно утверждать на приведенном коде - да. просто код реально мегапрост, чтоб где-то мог закрасться баг. если конечно это не баг asio. в чем сомневаюсь.. 

в этом большая ошибка
я много раз на это же полагался
а в итоге как раз в мегапростом коде и был баг ;)


Цитата(boostcoder @  28.3.2011,  15:18 Найти цитируемый пост)
нет. а как это сделать? добавить в недры asio вывод?
или есть какой-то еще способ?

написать враперы над send/recv/... из Libc
насколько я знаю, достаточно создать что-то типа wrappers.c, там реализовать обертки
вот реальный код подмены fork из какого-то проекта...
Код

#ifndef NO_PROCESS_LOCK
static pid_t (*_fork)();

HOOK_FUNCTION pid_t fork()
{
    pid_t pid;
#ifdef DEBUG
    fprintf(stdout, "fork()\n");
#endif
    start_fork();
    pid = _fork();
    if (pid == 0)
    {
    }
    else if (pid > 0)
    {
        end_fork();
    }
    return pid;
}
#endif

int PLogInit()
{
#ifndef NO_PROCESS_LOCK
    void *ptr;
    if ((ptr = dlsym(RTLD_NEXT, "fork")) == NULL)
    {
        fprintf(stderr, "dlsym() failed\n");
        return -1;
    }
    _fork = ptr;
#endif
    return 0;
}


Добавлено через 3 минуты и 2 секунды
Цитата(boostcoder @  28.3.2011,  18:49 Найти цитируемый пост)
баг воспроизводится всегда :(

в таком случае я уверен на 99% баг где-то в коде
думаю в вашем, а не asio


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
phprus
Дата 2.4.2011, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



Почитал я код и у меня возникло подозрение, что async_test() и asio в клиенте работают в разных потоках. А shared_array (как и shared_ptr) не может корректно передаваться между потоками (по крайней мере я пару месяцев назад не нашел такого способа).
Те когда выполняется код:
Код

boost::shared_array<char> buf(new char[send_buffer_size]);
sprintf(buf.get(), "cs:%8d\n", idx);
start_write(_sock, buf); // <----
if ( _ws ) {
     boost::this_thread::sleep(boost::posix_time::microseconds(1000));
}
 // <----

в отмеченных местах возникает состояние гонки, а так-же в функции start_write в вызове boost::bind происходят изменения в счетчике ссылок shared_array и последний ломается. Если не повезет один из деструкторов shared_array может убить данные раньше чем обновятся данные счетчика ссылок.

В свое время пару месяцев назад я напоролся на точно такой-же баг, но только с shared_ptr, через который между потоками передавался вектор. Весь процесс передачи был обернут мутексами, кроме участков, где возможно удаление временных объектов shared_ptr (а они возникали так как данные передавались через std::queue), но программа всеравно падала где-то в недрах asio. А иногда не падала, а что-то передавала.
И что самое паршивое в GCC все работало. А в Intel C++ падало или не падало. Зависело это от фазы луны, загрузки процессора и т. д.

В результате в этом месте я сделал полностью ручное управление памяти, а shared_ptr в области, где данные передаются между потоками я убрал полностью.

Потокобезопасность shared_ptr описана здесь: http://www.boost.org/doc/libs/1_46_1/libs/...tm#ThreadSafety (Example 3 описывает возникшую ситуацию).
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 2.4.2011, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



перевариваю...

Добавлено через 41 секунду
а по этой проблеме, которая у вас возникла, вы где-то на форуме тему создавали? хотелось бы почитать.
PM WWW   Вверх
phprus
Дата 2.4.2011, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



Нет, не создавал. Что-бы создать тему нужна была хоть какая-либо детализация проблемы, а у меня даже segmentation fault в разных местах всплывали. Я неделю думал, что на какой-то хитрый баг либо в asio либо в intel С++ наткнулся. Потом начал искать все места, который потенциально перераспределяли память и где рядом был обмен данными между потоками. С 3-й попытки заменил нужный shared_ptr на обычный ptr и ручное управление памятью и проблема ушла полностью.
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 2.4.2011, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



вручную управлять памятью страшно smile 
PM WWW   Вверх
phprus
Дата 2.4.2011, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



boostcoder
Везде да.
У меня к каждому клиенту привязан объект класса Client, который привязан к одному io_service и который гарантированно работает в одном потоке. В качестве буферов (которые и передаются asio) используется два std::vector<char>, как поля класса Client, а данные получаемые из другого потока в виде обычного указателя используются очень локализовано и после чего удаляются, по этому я и согласился на ручное управление памятью, а не стал дальше думать, как обойти такое ограничение shared_ptr.

Это сообщение отредактировал(а) phprus - 2.4.2011, 23:18
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 8.4.2011, 00:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



убрал из кода все смарт-поинтеры.
проблема осталась smile 

на стороне клиента, сохраняю отправляемые массивы в файл, чтоб убедится в том, что массивы не портятся.
так и есть. массивы не искаженны.
user posted image

на стороне сервера, так же, сохраняю принятые массивы.
но тут, массив приходит искаженным:
user posted image

вот снифф этого участка, tcpdump`ом, на стороне клиента:
user posted image

а это на стороне сервера:
user posted image



на стороне клиента, как раз в то место где данные искаженны, добавлены какие-то данные. не мои.
видно, что на стороне сервера, массив, после прочтения при помощи asio, уже испорчен. но tcpdump показывает что массив не испорчен.

я в замешательстве smile 


выложу код в тему, в надежде, что кто-то внесет ясность в ситуацию.

клиент:
Код


#include "header.hpp"

/***************************************************************************/

int main(int argc, char** argv) {
   if ( argc != 4 ) {
      std::cout << "client ip port 0/1 - sleed disabled/enabled" << std::endl;
      return 0;
   }
   std::string ip = argv[1];
   boost::uint16_t port = boost::lexical_cast<boost::uint16_t>(argv[2]);
   bool wsleep = (argv[3][0] == '1');
   std::cout << "sleep " << (wsleep?"enabled":"disabled") << std::endl;
   
   FILE* in = fopen("client_in.log", "wb");
   FILE* out= fopen("client_out.log", "wb");
   if ( !out || !in ) {
      std::cout << "can`t open file!" << std::endl;
      return 1;
   }

   boost::asio::ip::tcp::endpoint endpoint(
      boost::asio::ip::address::from_string(ip), port
   );

   boost::asio::io_service ios;
   boost::shared_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(ios));

   boost::thread thread(boost::bind(&boost::asio::io_service::run, &ios));
   
   boost::asio::ip::tcp::socket socket(ios);
   socket.connect(endpoint);

   boost::asio::socket_base::non_blocking_io non_blocking_io(true);
   socket.io_control(non_blocking_io);

   client_read(socket, in);

   for ( size_t idx = 0; idx < 100000000; ++idx ) {
      char* buf = new char[send_buffer_size];
      sprintf(buf, "cs:%8d\n", idx);
      start_write(socket, buf, out);
      if ( wsleep ) {
         boost::this_thread::sleep(boost::posix_time::microseconds(1000));
      }
   }

   std::cout
   << "send data to server finished!" << std::endl
   << "waiting for all ask`s from server..." << std::endl;

   work.reset();

   while ( counter ) {
      boost::this_thread::sleep(boost::posix_time::microseconds(1000));
      std::cout << "." << std::flush;
   }

   std::cout << std::endl << std::endl
   << "all ask`s received." << std::endl
   << "terminate client..." << std::endl;

   socket.cancel();
   socket.close();

   thread.join();
   fclose(in);
   fclose(out);
}

/***************************************************************************/

http://liveworkspace.org/code/15c1e78ea451...f1eebe7e08564a7

сервер:
Код


#include "header.hpp"

/***************************************************************************/

int main(int argc, char** argv) {
   if ( argc != 3 ) {
      std::cout << "server ip port" << std::endl;
      return 0;
   }
   std::string ip = argv[1];
   boost::uint16_t port = boost::lexical_cast<boost::uint16_t>(argv[2]);

   FILE* in = fopen("server_in.log", "wb");
   FILE* out= fopen("server_out.log", "wb");
   if ( !out || !in ) {
      std::cout << "can`t open file!" << std::endl;
      return 1;
   }

   boost::asio::ip::tcp::endpoint endpoint(
      boost::asio::ip::address::from_string(ip), port
   );
   
   boost::asio::io_service ios;
   boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
   boost::asio::ip::tcp::socket socket(ios);

   acceptor.accept(socket);
   std::cout << "new connection from: " << socket.remote_endpoint().address().to_string() << std::endl;
   
   boost::asio::socket_base::non_blocking_io non_blocking_io(true);
   socket.io_control(non_blocking_io);

   server_read(socket, in, out);

   ios.run();

   fclose(in);
   fclose(out);
}

/***************************************************************************/

http://liveworkspace.org/code/0a8e2cb728f8...d31f28c46ddf9e2

общий хидер:
Код


#ifndef _header_hpp_included_
#define _header_hpp_included_

#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/lexical_cast.hpp>

enum { recv_buffer_size = 13 };
enum { send_buffer_size = 13 };

volatile size_t counter = 0;

/***************************************************************************/

void client_readed(
   boost::asio::ip::tcp::socket&,
   char*,
   FILE*,
   const boost::system::error_code&
);

void client_read(
   boost::asio::ip::tcp::socket& sock,
   FILE* out
) {
   char* buf = new char[recv_buffer_size];
   boost::asio::async_read(
      sock,
      boost::asio::buffer(buf, recv_buffer_size),
      boost::bind(
         &client_readed,
         boost::ref(sock),
         buf,
         out,
         boost::asio::placeholders::error
      )
   );
}

void client_readed(
   boost::asio::ip::tcp::socket& sock,
   char* buf,
   FILE* out,
   const boost::system::error_code& e
) {
   if ( e ) {
      if ( !counter ) return;
      std::cout << "read handler: " << e.message() << std::endl;
      return;
   }

   fwrite(buf, recv_buffer_size, 1, out);

   counter--;

#ifdef _my_debug_
   printf("client_readed(): %s", buf);
   fflush(stdout);
#endif

   static size_t idx = 0;
   size_t tmp = 0;
   char* p = strchr(buf, ':');
   if ( p ) {
      p++;
      sscanf(p, "%8d", &tmp);
   } else {
      throw std::runtime_error("input data error!");
   }
   
   delete[] buf;
   
   if ( idx != tmp ) {
      std::ostringstream os;
      os << "read error. expected " << idx << " get " << tmp;
      throw std::runtime_error(os.str());
   }
   idx++;
   client_read(sock, out);
}

/***************************************************************************/

void writen(
   char*,
   FILE*,
   const boost::system::error_code&
);

void start_write(
   boost::asio::ip::tcp::socket& sock,
   char* buf,
   FILE* out
) {
   counter++;
   boost::asio::async_write(
      sock,
      boost::asio::buffer(buf, send_buffer_size),
      boost::bind(
         &writen,
         buf,
         out,
         boost::asio::placeholders::error
      )
   );
}

void writen(
   char* buf,
   FILE* out,
   const boost::system::error_code& e
) {
   fwrite(buf, send_buffer_size, 1, out);
   delete[] buf;
   if ( e ) {
      std::cout << "writen(): " << e.message() << std::endl;
   }
}

/***************************************************************************/

void server_readed(
   boost::asio::ip::tcp::socket&,
   char*,
   FILE*,
   FILE*,
   const boost::system::error_code&
);
   
void server_read(
   boost::asio::ip::tcp::socket& sock,
   FILE* in,
   FILE* out
) {
   char* buf = new char[recv_buffer_size];
   boost::asio::async_read(
      sock,
      boost::asio::buffer(buf, recv_buffer_size),
      boost::bind(
         &server_readed,
         boost::ref(sock),
         buf,
         in,
         out,
         boost::asio::placeholders::error
      )
   );
}

void server_readed(
   boost::asio::ip::tcp::socket& sock,
   char* buf,
   FILE* in,
   FILE* out,
   const boost::system::error_code& e
) {
   if ( e ) {
      std::cout << "read handler: " << e.message() << std::endl;
      return;
   }

#ifdef _my_debug_
   printf("server_readed(): %s", buf);
#endif

   fwrite(buf, recv_buffer_size, 1, in);
   
   static const char* ptr = "sc:";
   memcpy(buf, ptr, strlen(ptr));
   start_write(sock, buf, out);
   server_read(sock, in, out);
}

/***************************************************************************/

#endif // _header_hpp_included_


http://liveworkspace.org/code/fa23c521eab1...320dcff6290e656

всем спасибо.


зы
во вложении, архив с исходниками и Makefile`ом. проверено на gcc-linux и на mingw32.


Это сообщение отредактировал(а) boostcoder - 8.4.2011, 01:24

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  asiotest2.zip 2,78 Kb
PM WWW   Вверх
phprus
Дата 8.4.2011, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



Из замеченного при помощи wireshark:
Когда включен - TCP-сегменты ходят с данными ровно в 13 байт и у каждого стоит флаг PUSH (сразу отдавать на уровень выше, те приложению).
Когда sleep выключен сегменты содержат множество склееных блоков по 13 байт (возможно не целое число блоков).

А что говорят по этому поводу на https://svn.boost.org/trac/boost/ ? Может быть имеет смысл написать Bug report?
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 8.4.2011, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



при помощи strace обнаружил, что для ввода-вывода используются sendmsg() и recvmsg(), а не send() и recv() как предполагал.

Цитата(phprus @  8.4.2011,  10:02 Найти цитируемый пост)
Когда включен - TCP-сегменты ходят с данными ровно в 13 байт и у каждого стоит флаг PUSH (сразу отдавать на уровень выше, те приложению).
Когда sleep выключен сегменты содержат множество склееных блоков по 13 байт (возможно не целое число блоков).

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

Цитата(phprus @  8.4.2011,  10:02 Найти цитируемый пост)
А что говорят по этому поводу на https://svn.boost.org/trac/boost/ ? Может быть имеет смысл написать Bug report? 

та я потому и не писал, ибо все же не был уверен что это не мой баг в коде.
сейчас напишу..
PM WWW   Вверх
boostcoder
Дата 8.4.2011, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



вот что еще странно...
в один прекрасный момент, сервер принимает это:
user posted image

в первой строке сверху - все хорошо.
во второй и третьей строке, вместо завершающего нуля, вставлен символ c
в четвертой строке, символа c вначале, попросту нет.
PM WWW   Вверх
phprus
Дата 9.4.2011, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



boostcoder
Если sleep сделать с временем ожидания, равным 0 ( boost::this_thread::sleep(boost::posix_time::microseconds(0)) ) то  проблема тоже уходит, а sleep(0) в теории должен вызывать передачу управления другому процессу, те в коде похоже зарылась гонка. Только не могу понять в каком коде.

Цитата(boostcoder @  8.4.2011,  15:13 Найти цитируемый пост)
та я потому и не писал, ибо все же не был уверен что это не мой баг в коде.
сейчас напишу..

Сообщите пожалуйста ссылку на тикет.

Это сообщение отредактировал(а) phprus - 9.4.2011, 09:41
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 9.4.2011, 14:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(phprus @  9.4.2011,  09:38 Найти цитируемый пост)
sleep(0) в теории должен вызывать передачу управления другому процессу

по идее - да.

Цитата(phprus @  9.4.2011,  09:38 Найти цитируемый пост)
те в коде похоже зарылась гонка

не спорю... но где?! и как побороть?! smile 
PM WWW   Вверх
boostcoder
Дата 9.4.2011, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



phprus, так у тебя этот баг тоже воспроизводиться?
скажи как тестируешь? версии ОС, компилятора, boost? локально, удаленно?
PM WWW   Вверх
MAKCim
Дата 9.4.2011, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  8.4.2011,  00:44 Найти цитируемый пост)
на стороне клиента, как раз в то место где данные искаженны, добавлены какие-то данные. не мои.

ну так это может быть пустой пакет с tcp флагами...
хотя я не очень понимаю формат снифа

еще проверь у себя версию в аттаче
там логинг asio заменен а логинг sendmsg/recvmsg

Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  asiotest.rar 3,33 Kb


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
phprus
Дата 9.4.2011, 15:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



Цитата(boostcoder @  9.4.2011,  18:00 Найти цитируемый пост)
phprus, так у тебя этот баг тоже воспроизводиться?
скажи как тестируешь? версии ОС, компилятора, boost? локально, удаленно? 


Да, воспроизводится.
Boost 1.46.1
openSUSE 11.3 (2.6.34.7-0.7-desktop)
g++ (SUSE Linux) 4.5.0 20100604 [gcc-4_5-branch revision 160292]

Тестирую локально, путем запуска сервера и клиента с двух соседних консолей в Konsole.
PM MAIL WWW ICQ   Вверх
MAKCim
Дата 9.4.2011, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



и еще
вы пробовали запускать io_service::run не в отдельном потоке?


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
phprus
Дата 9.4.2011, 15:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



В реальной сети, с rtt min/avg/max/mdev = 5.226/5.250/5.281/0.023ms  баг воспроизводится значительно быстрее. В среднем до падения проходит 0,1 - 0,3 секунды, а в случае с локальным запуском код работает до падения минимум несколько секунд. Но тут boost 1.46.0 и CentOS с родным GCC 4.1.2.
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 9.4.2011, 15:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  9.4.2011,  15:14 Найти цитируемый пост)
еще проверь у себя версию в аттаче
там логинг asio заменен а логинг sendmsg/recvmsg

сделал. на локальной машине.
в аттаче. это 7z архив. расширение сменил потому что форум не позволяет приаттачивать 7z.

Цитата(MAKCim @  9.4.2011,  15:14 Найти цитируемый пост)
хотя я не очень понимаю формат снифа

скажите как сделать? а то я не очень разбираюсь в снифферах.

Добавлено @ 15:52
Цитата(MAKCim @  9.4.2011,  15:28 Найти цитируемый пост)
вы пробовали запускать io_service::run не в отдельном потоке?

в последних исходниках теста, сервер, я так и сделал.
а клиенту, помимо того, что отправлять сообщения в цикле, нужно еще и принимать ответы от сервера. потому там я оставил один поток.

Добавлено через 11 минут и 24 секунды
Цитата(phprus @  9.4.2011,  09:38 Найти цитируемый пост)
Если sleep сделать с временем ожидания, равным 0 ( boost::this_thread::sleep(boost::posix_time::microseconds(0)) ) то  проблема тоже уходит

проверил. у меня ничего не изменилось.
ubuntu-10.10
gcc-4.5.1
boost-1.46.1


Это сообщение отредактировал(а) boostcoder - 9.4.2011, 15:55

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  logs1.zip 139,60 Kb
PM WWW   Вверх
MAKCim
Дата 9.4.2011, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



boostcoder
Цитата(boostcoder @  9.4.2011,  15:49 Найти цитируемый пост)
а клиенту, помимо того, что отправлять сообщения в цикле, нужно еще и принимать ответы от сервера. потому там я оставил один поток.

эмм
так а в чем проблема это все делать в одном потоке?
делаешь async_read, потом async_write
далее run и уже в обработчиках written/readed генерируешь новые операции...

или я ошибаюсь?

Добавлено через 1 минуту и 14 секунд
в общем нужно, имхо, избавиться от более одного потока в клиенте и сервере
и снова проверить

Добавлено через 2 минуты и 4 секунды
Цитата(boostcoder @  8.4.2011,  00:44 Найти цитируемый пост)
вот снифф этого участка, tcpdump`ом, на стороне клиента:

вот я не понимаю, как этот скрин был получен


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
boostcoder
Дата 9.4.2011, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  9.4.2011,  16:01 Найти цитируемый пост)
делаешь async_read, потом async_write
далее run и уже в обработчиках written/readed генерируешь новые операции...

перед async_write данные нужно приготовить. допустим, добавлю функцию prepare_data, из нее вызову async_write. но если prepare_data вызвать снова из written - то это будет уже не тот тест. т.к. written вызывается когда, согласно документации:
Цитата

All of the data in the supplied buffers has been written. That is, the bytes transferred is equal to the sum of the buffer sizes.

но не понятно, куда "written". в какой-то буфер ОС? на другой конец?

кстати, сейчас обратил внимание на это:
Цитата

The program must ensure that the stream performs no other write operations (such as async_write, the stream's async_write_some function, or any other composed operations that perform writes) until this operation completes.

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

Добавлено @ 16:11
Цитата(MAKCim @  9.4.2011,  16:01 Найти цитируемый пост)
я не понимаю, как этот скрин был получен

просмотром в mc.

Добавлено @ 16:14
MAKCim, в тех логах что выложил последними, проглядывается такое:
user posted image

и такое:
user posted image

это в файле server_in.log


Это сообщение отредактировал(а) boostcoder - 9.4.2011, 16:16
PM WWW   Вверх
MAKCim
Дата 9.4.2011, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  9.4.2011,  16:11 Найти цитируемый пост)
т.е. я правильно понимаю, что пока не вызовется хэндлер async_write, нельзя запускать новую операцию записи?

выходит так


Цитата(boostcoder @  9.4.2011,  16:11 Найти цитируемый пост)
но не понятно, куда "written". в какой-то буфер ОС? на другой конец?

думаю, когда возвратились из системного вызова sendmsg, это и есть written

Добавлено через 26 секунд
Цитата(boostcoder @  9.4.2011,  16:11 Найти цитируемый пост)
просмотром в mc. 

так а причем тут tcpdump тогда?


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
boostcoder
Дата 9.4.2011, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(boostcoder @  9.4.2011,  16:11 Найти цитируемый пост)
т.е. я правильно понимаю, что пока не вызовется хэндлер async_write, нельзя запускать новую операцию записи?

или же имеется ввиду, не вызывать эту функцию из нескольких потоков для одного сокета? ибо я всегда так это примечание и понимал.
PM WWW   Вверх
MAKCim
Дата 9.4.2011, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  9.4.2011,  16:21 Найти цитируемый пост)
ли же имеется ввиду, не вызывать эту функцию из нескольких потоков для одного сокета? ибо я всегда так это примечание и понимал. 

если рассуждать логически, об этом (про потоки) было бы сказано, хотя не факт, конечно
поэтому я и предлагаю как-нибудь исхитриться и не юзать таки более одного потока


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
boostcoder
Дата 9.4.2011, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  9.4.2011,  16:17 Найти цитируемый пост)
так а причем тут tcpdump тогда? 

нет. те скрины что сделаны tcpdump`ом, я комментировал как скрины сделанные tcpdump`ом.
вот они:
http://clip2net.com/clip/m47996/1300879093-1-262kb.png
http://clip2net.com/clip/m47996/1300879448-2-27kb.png
http://clip2net.com/clip/m47996/1300879665-3-21kb.png
http://clip2net.com/clip/m47996/1300879710-4-22kb.png

и последние два:
http://clip2net.com/clip/m47996/1302213996...zb3346-11kb.png
http://clip2net.com/clip/m47996/1302214240...psa3346-4kb.png

т.е., на сколько я понял, для продолжения, нужно переписать клиент так, чтоб следующая запись производилась по окончанию предыдущей?
ок. сейчас.

Добавлено через 38 секунд
Цитата(MAKCim @  9.4.2011,  16:25 Найти цитируемый пост)
предлагаю как-нибудь исхитриться и не юзать таки более одного потока

ок.
сейчас делаю.

PM WWW   Вверх
boostcoder
Дата 9.4.2011, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



переписал как договаривались, без единого потока, и с запуском следующей операции записи по завершению предыдущей.
работает значительно дольше, но все равно валится(только при запуске клиента и сервера локально):
исходники + логи, тут: http://rghost.ru/5141178

выложу в тему исходники. может я в коде что-то намудрил.. сам не замечаю..

клиент:
Код


#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>

#include "header.hpp"

/***************************************************************************/

void readed(
   boost::asio::ip::tcp::socket&,
   char*,
   FILE*,
   const boost::system::error_code&
);

void start_read(
   boost::asio::ip::tcp::socket& sock,
   FILE* out
) {
   char* buf = new char[recv_buffer_size];
   boost::asio::async_read(
      sock,
      boost::asio::buffer(buf, recv_buffer_size),
      boost::bind(
         &readed,
         boost::ref(sock),
         buf,
         out,
         boost::asio::placeholders::error
      )
   );
}

void readed(
   boost::asio::ip::tcp::socket& sock,
   char* buf,
   FILE* out,
   const boost::system::error_code& e
) {
   if ( e ) {
      std::cout << "read handler: " << e.message() << std::endl;
      return;
   }
   
   //   fwrite(buf, recv_buffer_size, 1, out);
   
   static size_t idx = 0;
   size_t tmp = 0;
   char* p = strchr(buf, ':');
   if ( p ) {
      sscanf(p+1, "%8d", &tmp);
   } else {
      throw std::runtime_error("input data error!");
   }
   
   delete[] buf;
   
   if ( idx != tmp ) {
      std::ostringstream os;
      os << "read error. expected " << idx << " get " << tmp;
      throw std::runtime_error(os.str());
   }
   idx++;
   start_read(sock, out);
}

/***************************************************************************/

void writen(
   boost::asio::ip::tcp::socket&,
   char*,
   FILE*,
   const boost::system::error_code&
);

void start_write(
   boost::asio::ip::tcp::socket& sock,
   FILE* out
) {
   static size_t idx = 0;
   
   char* buf = new char[send_buffer_size];
   sprintf(buf, "cs:%8d\n", idx);
   idx++;

   boost::asio::async_write(
      sock,
      boost::asio::buffer(buf, send_buffer_size),
      boost::bind(
         &writen,
         boost::ref(sock),
         buf,
         out,
         boost::asio::placeholders::error
      )
   );
}

void writen(
   boost::asio::ip::tcp::socket& sock,
   char* buf,
   FILE* out,
   const boost::system::error_code& e
) {
   //   fwrite(buf, send_buffer_size, 1, out);
   delete[] buf;
   if ( e ) {
      std::cout << "writen(): " << e.message() << std::endl;
   }
   
   start_write(sock, out);
}

/***************************************************************************/

int main(int argc, char** argv) {
   if ( argc != 4 ) {
      std::cout << "client ip port 0/1 - sleed disabled/enabled" << std::endl;
      return 0;
   }
   if (init_wrappers())
   {
      return -1;
   }
   std::string ip = argv[1];
   boost::uint16_t port = boost::lexical_cast<boost::uint16_t>(argv[2]);
   bool wsleep = (argv[3][0] == '1');
   std::cout << "sleep " << (wsleep?"enabled":"disabled") << std::endl;
   
   FILE* in = fopen("client_in.log", "wb");
   FILE* out= fopen("client_out.log", "wb");
   dbg::in = in;
   dbg::out = out;
   if ( !out || !in ) {
      std::cout << "can`t open file!" << std::endl;
      return 1;
   }

   boost::asio::ip::tcp::endpoint endpoint(
      boost::asio::ip::address::from_string(ip), port
   );

   boost::asio::io_service ios;
   boost::asio::ip::tcp::socket socket(ios);
   socket.connect(endpoint);

   boost::asio::socket_base::non_blocking_io non_blocking_io(true);
   socket.io_control(non_blocking_io);

   start_write(socket, out);
   start_read(socket, in);

   ios.run();

   fclose(in);
   fclose(out);
}

/***************************************************************************/



сервер:
Код


#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>

#include "header.hpp"

/***************************************************************************/

void writen(
   boost::asio::ip::tcp::socket& sock,
   char* buf,
   FILE* out,
   const boost::system::error_code& e
);

void start_write(
   boost::asio::ip::tcp::socket& sock,
   char* buf,
   FILE* out
) {
   boost::asio::async_write(
      sock,
      boost::asio::buffer(buf, send_buffer_size),
      boost::bind(
         &writen,
         boost::ref(sock),
         buf,
         out,
         boost::asio::placeholders::error
      )
   );
}

void writen(
   boost::asio::ip::tcp::socket& sock,
   char* buf,
   FILE* out,
   const boost::system::error_code& e
) {
   //   fwrite(buf, send_buffer_size, 1, out);
   delete[] buf;
   if ( e ) {
      std::cout << "writen(): " << e.message() << std::endl;
   }
}

void readed(
   boost::asio::ip::tcp::socket&,
   char*,
   FILE*,
   FILE*,
   const boost::system::error_code&
);

void start_read(
   boost::asio::ip::tcp::socket& sock,
   FILE* in,
   FILE* out
) {
   char* buf = new char[recv_buffer_size];
   boost::asio::async_read(
      sock,
      boost::asio::buffer(buf, recv_buffer_size),
      boost::bind(
         &readed,
         boost::ref(sock),
         buf,
         in,
         out,
         boost::asio::placeholders::error
      )
   );
}

void readed(
   boost::asio::ip::tcp::socket& sock,
   char* buf,
   FILE* in,
   FILE* out,
   const boost::system::error_code& e
) {
   if ( e ) {
      std::cout << "read handler: " << e.message() << std::endl;
      return;
   }
   
   #ifdef _my_debug_
   printf("server_readed(): %s", buf);
   #endif
   
   //   fwrite(buf, recv_buffer_size, 1, in);
   
   static const char* ptr = "sc:";
   memcpy(buf, ptr, strlen(ptr));
   start_write(sock, buf, out);
   start_read(sock, in, out);
}

/***************************************************************************/

int main(int argc, char** argv) {
   if ( argc != 3 ) {
      std::cout << "server ip port" << std::endl;
      return 0;
   }
   if (init_wrappers())
   {
      return -1;
   }
   std::string ip = argv[1];
   boost::uint16_t port = boost::lexical_cast<boost::uint16_t>(argv[2]);

   FILE* in = fopen("server_in.log", "wb");
   FILE* out= fopen("server_out.log", "wb");
   dbg::in = in;
   dbg::out = out;
   if ( !out || !in ) {
      std::cout << "can`t open file!" << std::endl;
      return 1;
   }

   boost::asio::ip::tcp::endpoint endpoint(
      boost::asio::ip::address::from_string(ip), port
   );
   
   boost::asio::io_service ios;
   boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
   boost::asio::ip::tcp::socket socket(ios);

   acceptor.accept(socket);
   std::cout << "new connection from: " << socket.remote_endpoint().address().to_string() << std::endl;
   
   boost::asio::socket_base::non_blocking_io non_blocking_io(true);
   socket.io_control(non_blocking_io);

   start_read(socket, in, out);

   ios.run();

   fclose(in);
   fclose(out);
}

/***************************************************************************/



общий хидер:
Код


#ifndef _header_hpp_included_
#define _header_hpp_included_

#include <cstdio>

enum { recv_buffer_size = 13 };
enum { send_buffer_size = 13 };

namespace dbg  {
   extern FILE *in;
   extern FILE *out;
};

extern int init_wrappers();

#endif // _header_hpp_included_



на клиент, в один прекрасный, приходит это:
user posted image

тут две ошибки:
1. склеились две части "sc".
2. клиент ожидает 3574549, а пришло 3574550.

Добавлено @ 17:32
вот что еще странно.
в server_out.log есть такое:
user posted image
т.е. одно и то же значение повторяется дважды.

хотя, в server_in.log этого нет:
user posted image

странно..

Это сообщение отредактировал(а) boostcoder - 9.4.2011, 19:31
PM WWW   Вверх
boostcoder
Дата 9.4.2011, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



запустил сервер на удаленной машине - вроде работает. уже минут 10ть.

...
уже пол часа.

Это сообщение отредактировал(а) boostcoder - 9.4.2011, 18:45
PM WWW   Вверх
boostcoder
Дата 9.4.2011, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  9.4.2011,  16:17 Найти цитируемый пост)
думаю, когда возвратились из системного вызова sendmsg, это и есть written

а возврат из sendmsg() когда происходит? что-то немогу в доках найти этого момента..
дело в том, что скорость очень сильно упала.
сейчас, используется около 17% от пропускной способности.
чем это может быть вызвано?
PM WWW   Вверх
boostcoder
Дата 9.4.2011, 19:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(boostcoder @  9.4.2011,  18:53 Найти цитируемый пост)
сейчас, используется около 17% от пропускной способности.

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

requests: 30074
answers : 29336

requests: 35086
answers : 31368

requests: 15037
answers : 19062

requests: 21615
answers : 22223

requests: 23491
answers : 22525

requests: 25062
answers : 23057

requests: 15037
answers : 16040

requests: 15037
answers : 15593

requests: 20049
answers : 20272

requests: 30074
answers : 25723

requests: 25061
answers : 27965

requests: 25558
answers : 28553

requests: 29574
answers : 22346

requests: 20049
answers : 25841




вот только решить бы еще проблему порчи данных при запуске клиента и сервера локально..


Это сообщение отредактировал(а) boostcoder - 9.4.2011, 19:53
PM WWW   Вверх
phprus
Дата 9.4.2011, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



Цитата(boostcoder @  9.4.2011,  20:25 Найти цитируемый пост)
переписал как договаривались, без единого потока, и с запуском следующей операции записи по завершению предыдущей.
работает значительно дольше, но все равно валится:

А в сервере это условие выполняется?
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 9.4.2011, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(phprus @  9.4.2011,  19:14 Найти цитируемый пост)
А в сервере это условие выполняется?

да.
сервер реализован по принципу реакции. пришли данные от клиента - отсылается ответ. и только после этого запускается следующая операция чтения.

Добавлено через 4 минуты и 41 секунду
коды несколькими постами выше.


Это сообщение отредактировал(а) boostcoder - 9.4.2011, 19:26
PM WWW   Вверх
boostcoder
Дата 9.4.2011, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(boostcoder @  9.4.2011,  18:53 Найти цитируемый пост)
а возврат из sendmsg() когда происходит?

наверное тогда же, когда и send(). но в тестах, сокеты находятся в неблокирующем режиме.

Цитата(boostcoder @  9.4.2011,  19:10 Найти цитируемый пост)
возможно это из-за того, что происходит почти симметричных обмен? т.е. кол-во входящих и исходящих данных почти равно.

получается что нет. т.к. изменил клиента и сервера так, что клиент только шлет, а сервер только принимает. никаких ответов обратно не шлется. скорость не увеличилась...

...

увеличил размер массивов с 13 байт до 1024 байт. использование канала не увеличилось.
получается так, что тормозом в данной ситуации является sendmsg().


Это сообщение отредактировал(а) boostcoder - 9.4.2011, 20:02
PM WWW   Вверх
boostcoder
Дата 9.4.2011, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



запустил параллельно тесту торрент-клиент, и все стало еще интересней smile 

в client_out.log стало наблюдаться такое:
user posted image
и такое:
user posted image
и такое:
user posted image
и т.д...


в server_in.log такое:
user posted image
и такое:
user posted image

бред какой-то...

последняя версия исходников во вложении.


Это сообщение отредактировал(а) boostcoder - 9.4.2011, 20:33

Присоединённый файл ( Кол-во скачиваний: 1 )
Присоединённый файл  asiotest2.zip 3,54 Kb
PM WWW   Вверх
mes
Дата 9.4.2011, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата

Код

void writen(
   ...
   start_write(sock, out);
}



что то этот момент меня сильно смущает..


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 9.4.2011, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



mes, что именно в этом моменте Вас смущает?

PM WWW   Вверх
mes
Дата 9.4.2011, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



start_write из writen.. 


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 9.4.2011, 20:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



и?
запуск следующей записи когда предыдущая завершилась.
PM WWW   Вверх
mes
Дата 9.4.2011, 21:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  9.4.2011,  19:58 Найти цитируемый пост)
и?

не знаю, но интуитивно глаз спотыкается на этом месте.. 
остальной код подозрений не вызывает.. 


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 9.4.2011, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



mes, на то он и _completion_handler_ чтоб из него производить некоторые действия по окончанию асинхронной операции.
PM WWW   Вверх
mes
Дата 9.4.2011, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



в бустовых примерах подобное применение имеется ?


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 9.4.2011, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  9.4.2011,  21:30 Найти цитируемый пост)
в бустовых примерах подобное применение имеется ?

конечно. почти в каждом примере, где одна асинхронная операция создает другую.

зы
да и чем вызов start_write() из хэндлера, отличается от вызова из какого-то другого места?

Это сообщение отредактировал(а) boostcoder - 9.4.2011, 22:05
PM WWW   Вверх
boostcoder
Дата 9.4.2011, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



странно все это..
при загрузке сети, иногда валится, иногда нет...
любопытно, почему когда валится, в хэндлер не передается ошибка. хотя должна. т.е. из этого следует, что asio думает что все гуд smile

Добавлено через 6 минут и 54 секунды
опять свалилось :(

клиент ожидал 8475039, а получил 84
user posted image

обратите внимание. значение 8475038 повторяется дважды.

и еще одна странность. клиент упал с таким сообщением:
Цитата

terminate called after throwing an instance of 'std::runtime_error'
  what():  read error. expected 8475039 get 84

а пришло 847  smile

Добавлено через 12 минут и 27 секунд
 smile 
PM WWW   Вверх
mes
Дата 9.4.2011, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



попробуйте обнулять тот буффер, который создаете..


--------------------
PM MAIL WWW   Вверх
mes
Дата 9.4.2011, 23:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата

//  fwrite(buf, recv_buffer_size, 1, out);

а записанное выглядит ровно, без сомнений ?

Добавлено через 49 секунд
Цитата(boostcoder @  9.4.2011,  20:26 Найти цитируемый пост)
 на то он и _completion_handler_ 

да, тут зря я придрался.. 


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 9.4.2011, 23:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  9.4.2011,  22:52 Найти цитируемый пост)
попробуйте обнулять тот буффер, который создаете..

попробовал. на обоих сторонах.
при загруженной сети, клиент свалился с таким сообщением:
Цитата

terminate called after throwing an instance of 'std::runtime_error'
  what():  read error. expected 92410192 get 92410


во входящем буфере клиента было это:
user posted image
опять одно и то же значение повторяется дважды.

сервер отправил это:
user posted image


и снова непонятка... клиент говорит что получено 92410. но такого сообщения в входящих нет! smile 

это ###..

Добавлено @ 23:51
Цитата(mes @  9.4.2011,  23:31 Найти цитируемый пост)
а записанное выглядит ровно, без сомнений ?

на скринах, где я упоминаю server_*.log и client_*.log - это и есть то, что записано. т.е. сырые данные.

Добавлено @ 23:55
Цитата(boostcoder @  9.4.2011,  23:50 Найти цитируемый пост)
но такого сообщения в входящих нет!

кстати!
клиент падает по необработанному исключению. а в этом случае, файловые буфера сброшены не будут. потому я в логах не увижу последних данных.

сейчас повешу обработчик, и повторю тест.

Это сообщение отредактировал(а) boostcoder - 9.4.2011, 23:55
PM WWW   Вверх
mes
Дата 10.4.2011, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  9.4.2011,  22:50 Найти цитируемый пост)
во входящем буфере клиента было это:

какой именно буффер ? а то что то я запутался..

Добавлено через 1 минуту и 37 секунд
Цитата(boostcoder @  9.4.2011,  22:50 Найти цитируемый пост)
, клиент свалился с таким сообщением:

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


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 00:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  10.4.2011,  00:00 Найти цитируемый пост)
какой именно буффер ?

вы последний выложенный мной архив с исходниками качали? смотрели их? чтоб я знал с какой стороны объяснять..
PM WWW   Вверх
mes
Дата 10.4.2011, 00:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



попробуйте убрать из readed весь анализ приходящих данных и оставить только запись в файл.. 
только буффер не забудьте обнулять..

Цитата(boostcoder @  9.4.2011,  23:02 Найти цитируемый пост)
архив с исходниками качали? смотрели их?

да смотрел и как раз смотрю их.. 

Это сообщение отредактировал(а) mes - 10.4.2011, 00:08


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 00:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  10.4.2011,  00:06 Найти цитируемый пост)
весь анализ приходящих данных

вот это?:
Код

   char* p = strchr(buf, ':');
   if ( p ) {
      sscanf(p+1, "%8d", &tmp);
   } else {
      throw std::runtime_error("input data error!");
   }
   
   if ( idx != tmp ) {
      std::ostringstream os;
      os << "read error. expected " << idx << " get " << tmp;
      throw std::runtime_error(os.str());
   }


как же я тогда узнаю об ошибке?


Цитата(mes @  10.4.2011,  00:06 Найти цитируемый пост)
да смотрел и как раз смотрю их..

там есть файл wrappers.cpp, его Максим добавил. логи пишутся из оберток над sendmsg() и recvmsg(). т.е. по идее на 100% точно отражают происходящее.

PM WWW   Вверх
mes
Дата 10.4.2011, 00:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  9.4.2011,  22:50 Найти цитируемый пост)
 server_*.log и client_*.log - это и есть то, что записано. т.е. сырые данные.

поставьте после каждой записи сырых данных еще запись какой нибудь последовательности..

Добавлено через 1 минуту и 24 секунды
Цитата(boostcoder @  9.4.2011,  23:11 Найти цитируемый пост)
как же я тогда узнаю об ошибке?

если вы о исключении, то запись дополнительной последовательности в файл должна показать причину.. 


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  10.4.2011,  00:14 Найти цитируемый пост)
запись какой нибудь последовательности..

Цитата(mes @  10.4.2011,  00:14 Найти цитируемый пост)
запись дополнительной последовательности в файл должна показать причину..

поясните. не понял.

Добавлено через 3 минуты и 58 секунд
еще, на сервере во входящих есть такое:
user posted image

в hex:
user posted image
т.е. три нуля.

PM WWW   Вверх
mes
Дата 10.4.2011, 00:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



после каждого сброса буффера в файл записывайте туда еще например "$$$"
чтоб наглядно бросалась в глаза.. 


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 00:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  10.4.2011,  00:22 Найти цитируемый пост)
после каждого сброса буффера в файл

но мне не известно когда буфера сбрасываются.
все что я могу, это принудительно вызывать fflush(). т.е. предлагаете вставить вызовы fflush() в обертки над sendmsg() и recvmsg() ?

Добавлено через 6 минут и 4 секунды
mes, я обернул код клиента в try-catch блок. теперь буфера не потеряются.
есть ли смысл сбрасывать буфера после каждой записи в файл?

Добавлено через 11 минут и 5 секунд
теперь свалился с таким сообщением:
Цитата

(exception): read error. expected 6690986 get 6690987

в client_in.log такое:
user posted image

число 6690985 повторяется дважды. хотя второе должно было быть 6690986
и пропал символ c и : 
PM WWW   Вверх
mes
Дата 10.4.2011, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



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


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 00:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



сервер вот что отправил:
user posted image
последние две строки повторяются.
PM WWW   Вверх
mes
Дата 10.4.2011, 00:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



в общем  у меня сложилось впечатление, что у Вас были две ошибки, которые создали эту ситуацию..
1. чтение не полной записи с сокета, а следовательно невозможность получения ожидаемого индекса используемым способом
2. не обнуление буффера, которое  приводило к появлению неожидаемых символов.. 



--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 00:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



еще раз свалилось.
user posted image
тут уже повторение с предыдущими запусками. опять повтор. и опять пропали два символа.

Добавлено @ 00:48
Цитата(mes @  10.4.2011,  00:42 Найти цитируемый пост)
1. чтение не полной записи с сокета, а следовательно невозможность получения ожидаемого индекса используемым способом

это от меня не зависит. согласно документации, хэндлер вызовется в случае:
Цитата

The asynchronous operation will continue until one of the following conditions is true:
1. The supplied buffers are full. That is, the bytes transferred is equal to the sum of the buffer sizes.
2. An error occurred.


с другой стороны, в последних трех скринах ситуация повторилась.

Цитата(mes @  10.4.2011,  00:42 Найти цитируемый пост)
2. не обнуление буффера, которое  приводило к появлению неожидаемых символов..

это я сделал.


Это сообщение отредактировал(а) boostcoder - 10.4.2011, 00:51
PM WWW   Вверх
mes
Дата 10.4.2011, 01:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  9.4.2011,  23:25 Найти цитируемый пост)
в client_in.log такое:

сорри.. наверно ночь сказывается, но я  так и не понял откуда данные попадают в этот лог..

Добавлено через 1 минуту и 8 секунд
Цитата(boostcoder @  9.4.2011,  23:25 Найти цитируемый пост)
есть ли смысл сбрасывать буфера после каждой записи в файл?

не в сбрасывании цель, а в добавлении визуального разделителя..

Добавлено через 7 минут и 5 секунд
Цитата(boostcoder @  9.4.2011,  23:46 Найти цитируемый пост)
это от меня не зависит. 

просто Вы не в праве применять scanf до тех пор пока не наполните свой буффер.. 



--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 01:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  10.4.2011,  01:00 Найти цитируемый пост)
я  так и не понял откуда данные попадают в этот лог

в client.cpp есть такой код:
Код

   FILE* in = fopen("server_in.log", "wb");
   FILE* out= fopen("server_out.log", "wb");
   dbg::in = in; // dbg::in и dbg::out используются в wrappers.cpp
   dbg::out = out;

в wrappers.cpp есть такое:
Код

static void dump(const struct msghdr *msg, FILE *fp)
{
    size_t i;
    for (i = 0; i < msg->msg_iovlen; ++i)
    {
        struct iovec *iov = &msg->msg_iov[i];
        fwrite(iov->iov_base, iov->iov_len, 1, fp);
    }
}

extern "C"
{

ssize_t (*_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
ssize_t (*_recvmsg)(int sockfd, struct msghdr *msg, int flags);

ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)
{
    if (dbg::out)
    {
        dump(msg, dbg::out); // запись отсылаемого
    }
    return _sendmsg(sockfd, msg, flags);
}

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
{
    ssize_t error;
    error = _recvmsg(sockfd, msg, flags);
    if (dbg::in && error > 0)
    {
        dump(msg, dbg::in); // запись принятого
    }
    return error;
}

}



Добавлено через 1 минуту и 11 секунд
Цитата(mes @  10.4.2011,  01:00 Найти цитируемый пост)
Вы не в праве применять scanf до тех пор пока не наполните свой буффер

так scanf() вызывается в хэндлере. а хэндлер вызывается тогда, когда указанный объем прочитан.
PM WWW   Вверх
mes
Дата 10.4.2011, 01:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  00:08 Найти цитируемый пост)
так scanf() вызывается в хэндлере. а хэндлер вызывается тогда, когда указанный объем прочитан. 

сделайте strlen перед этим для проверки и будет ясно там ли мы ищем причину..

Добавлено @ 01:15
Цитата(boostcoder @  10.4.2011,  00:08 Найти цитируемый пост)
в wrappers.cpp есть такое:

тогда, если подозрения правильные, то ошибки должны быть в server_out и в client_in
но не в двух других..

Это сообщение отредактировал(а) mes - 10.4.2011, 01:32


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 05:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  10.4.2011,  01:11 Найти цитируемый пост)
сделайте strlen перед этим для проверки и будет ясно там ли мы ищем причину..

сделал.

Цитата(mes @  10.4.2011,  01:11 Найти цитируемый пост)
тогда, если подозрения правильные, то ошибки должны быть в server_out и в client_in
но не в двух других..

Вы правы.
вот только я немогу понять закономерность...

клиент свалился с таким сообщением:
Цитата

expected: 10661261, get: 1066126, buf:  1066126 1expected: 10661262, get: 661262, buf: 0661262
 1expected: 10661263, get: 661263, buf: 0661263
...

где:
"expected: 10661261" - правильно. это и должно было прийти.
"get: 1066126" - тут, внезапно, пропал последний знак.
"buf:  1066126" - тут его тоже нет.
"1expected: 10661262" - а ни это ли наша пропавшая единичка?;) на ее месте должен быть символ перевода строки.
"get: 661262" - тут нет первых двух знаков. т.е. "10"
"buf: 0661262" - а тут нет только первой единички.

сервер получил это:
user posted image
а отослал это:
user posted image
значение 10661262 повторяется дважды.

а клиент получил это:
user posted image


ну что, кто-то раскусил головоломку? ;)

последняя версия кодов.
клиент:
Код


#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/lexical_cast.hpp>

#include "header.hpp"

size_t req_cnt = 0;
size_t ask_cnt = 0;
size_t requests = 0;
size_t answers = 0;
bool wsleep = false;

void timer_func() {
   while ( true ) {
      std::cout
      << "per sec requests: " << requests << std::endl
      << "per sec answers : " << answers << std::endl
      << "total requests  : " << req_cnt << std::endl
      << "total answers   : " << ask_cnt << std::endl << std::endl;
      requests = answers = 0;
      boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
   }
}

/***************************************************************************/

void readed(boost::asio::ip::tcp::socket&,
            char*,
            const boost::system::error_code&,
            size_t);

void start_read(boost::asio::ip::tcp::socket& sock) {
   char* buf = new char[recv_buffer_size];
   memset(buf, 0, recv_buffer_size);
   boost::asio::async_read(
      sock,
      boost::asio::buffer(buf, recv_buffer_size),
      boost::bind(
         &readed,
         boost::ref(sock),
         buf,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred
      )
   );
}

void readed(boost::asio::ip::tcp::socket& sock,
            char* buf,
            const boost::system::error_code& e,
            size_t rd)
{
   if ( e ) {
      throw std::runtime_error("readed(): " + e.message());
   }

   if ( rd != recv_buffer_size ) {
      std::cout
      << "readed(): " << buf << ", len: " << rd << std::endl;
   }

   static size_t idx = 0;
   size_t tmp = atoi(buf);
   
   if ( idx != tmp ) {
      std::cout
      << "expected: " << idx << ", get: " << tmp << ", buf: " << buf;
   }

   delete[] buf;

   answers++;
   ask_cnt++;

   ++idx;

   start_read(sock);
}

/***************************************************************************/

void writen(boost::asio::ip::tcp::socket&,
            char*,
            const boost::system::error_code&,
            size_t);

void start_write(boost::asio::ip::tcp::socket& sock) {
   static size_t idx = 0;
   requests++;
   req_cnt++;
   
   char* buf = new char[send_buffer_size];
   memset(buf, 0, send_buffer_size);
   sprintf(buf, "%9d\n", idx++);

   boost::asio::async_write(
      sock,
      boost::asio::buffer(buf, send_buffer_size),
      boost::bind(
         &writen,
         boost::ref(sock),
         buf,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred
      )
   );
}

void writen(boost::asio::ip::tcp::socket& sock,
            char* buf,
            const boost::system::error_code& e,
            size_t wr)
{
   if ( e ) {
      throw std::runtime_error("writen(): " + e.message());
   }

   if ( wr != send_buffer_size ) {
      std::cout
      << "writen(): " << buf << ", len: " << wr << std::endl;
   }

   delete[] buf;

   if ( wsleep ) {
      boost::this_thread::sleep(boost::posix_time::microseconds(1000));
   }
   
   start_write(sock);
}

/***************************************************************************/

int main(int argc, char** argv) {
   try {
      if ( argc != 4 ) {
         std::cout << "client ip port 0/1 - sleed disabled/enabled" << std::endl;
         return 0;
      }

      if (init_wrappers()) {
         return -1;
      }
      std::string ip = argv[1];
      boost::uint16_t port = atoi(argv[2]);
      wsleep = (argv[3][0] == '1');
      std::cout << "sleep " << (wsleep?"enabled":"disabled") << std::endl;

      boost::thread thread(&timer_func);

      dbg::in = fopen("client_in.log", "wb");
      dbg::out= fopen("client_out.log", "wb");
      if ( !dbg::out || !dbg::in ) {
         std::cout << "can`t open file!" << std::endl;
         return 1;
      }

      boost::asio::ip::tcp::endpoint endpoint(
         boost::asio::ip::address::from_string(ip), port
      );

      boost::asio::io_service ios;
      boost::asio::ip::tcp::socket socket(ios);
      socket.connect(endpoint);

//      boost::asio::socket_base::non_blocking_io non_blocking_io(true);
//      socket.io_control(non_blocking_io);

      start_write(socket);
      start_read(socket);

      ios.run();

   } catch ( const std::exception& e ) {
      std::cout << "(exception): " << e.what() << std::endl;
   }
   fclose(dbg::in);
   fclose(dbg::out);
}

/***************************************************************************/


сервер:
Код


#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>

#include "header.hpp"

/***************************************************************************/

void writen(boost::asio::ip::tcp::socket&,
            char*,
            const boost::system::error_code&,
            size_t);

void start_write(boost::asio::ip::tcp::socket& sock, char* buf) {
   boost::asio::async_write(
      sock,
      boost::asio::buffer(buf, send_buffer_size),
      boost::bind(
         &writen,
         boost::ref(sock),
         buf,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred
      )
   );
}

void writen(boost::asio::ip::tcp::socket& sock,
            char* buf,
            const boost::system::error_code& e,
            size_t wr)
{
   if ( e ) {
      throw std::runtime_error("writen(): " + e.message());
   }

   if ( wr != send_buffer_size ) {
      std::cout
      << "writen(): " << buf << ", len: " << wr << std::endl;
   }

   delete[] buf;
}

void readed(boost::asio::ip::tcp::socket&,
            char*,
            const boost::system::error_code&,
            size_t);

void start_read(boost::asio::ip::tcp::socket& sock) {
   char* buf = new char[recv_buffer_size];
   memset(buf, 0, recv_buffer_size);
   boost::asio::async_read(
      sock,
      boost::asio::buffer(buf, recv_buffer_size),
      boost::bind(
         &readed,
         boost::ref(sock),
         buf,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred
      )
   );
}

void readed(boost::asio::ip::tcp::socket& sock,
            char* buf,
            const boost::system::error_code& e,
            size_t rd)
{
   if ( e ) {
      throw std::runtime_error("read handler: " + e.message());
   }

   if ( rd != recv_buffer_size ) {
      std::cout
      << "readed(): " << buf << ", len: " << rd << std::endl;
   }

   static size_t idx = 0;
   size_t tmp = atoi(buf);
   if ( idx != tmp ) {
      fprintf(stdout, "expected: %9d, get: %9d, buf: %s", idx, tmp, buf);
      fflush(stdout);
   }

   ++idx;

   start_write(sock, buf);
   start_read(sock);
}

/***************************************************************************/

int main(int argc, char** argv) {
   if ( argc != 3 ) {
      std::cout << "server ip port" << std::endl;
      return 0;
   }

   if ( init_wrappers() ) {
      return -1;
   }
   try {
      std::string ip = argv[1];
      boost::uint16_t port = atoi(argv[2]);

      dbg::in = fopen("server_in.log", "wb");
      dbg::out= fopen("server_out.log", "wb");
      if ( !dbg::out || !dbg::in ) {
         std::cout << "can`t open file!" << std::endl;
         return 1;
      }

      boost::asio::ip::tcp::endpoint endpoint(
         boost::asio::ip::address::from_string(ip), port
      );

      boost::asio::io_service ios;
      boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
      boost::asio::ip::tcp::socket socket(ios);

      acceptor.accept(socket);
      std::cout << "new connection from: " << socket.remote_endpoint().address().to_string() << std::endl;

   //   boost::asio::socket_base::non_blocking_io non_blocking_io(true);
   //   socket.io_control(non_blocking_io);

      start_read(socket);

      ios.run();
   } catch ( const std::exception& e ) {
      std::cout << "(exception): " << e.what() << std::endl;
   }

   fclose(dbg::in);
   fclose(dbg::out);
}

/***************************************************************************/




Это сообщение отредактировал(а) boostcoder - 10.4.2011, 05:49

Присоединённый файл ( Кол-во скачиваний: 1 )
Присоединённый файл  asiotest2.zip 3,66 Kb
PM WWW   Вверх
boostcoder
Дата 10.4.2011, 06:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



я сделал это!!! smile 

ща расскажу..
PM WWW   Вверх
boostcoder
Дата 10.4.2011, 06:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



обратите внимание на этот код из сервера:
Код

void readed(boost::asio::ip::tcp::socket& sock,
            char* buf,
            const boost::system::error_code& e,
            size_t rd)
{
   ...

   start_write(sock, buf);
   start_read(sock); <<<<<<<<<<<<<<<<<<<<<<
}


последовательность такая:
readed() вызывается когда данные прочитаны. из него я запускаю операцию записи и операцию чтения. и тут ошибка! операцию чтения нужно запускать из хэндлера операции записи. т.е. мало того что в доке намекается на то, что нельзя выполнять две операции записи и чтения одновременно, так оказывается что выполнять чтение пока не завершена запись(и наоборот) тоже нельзя!

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

зы
немного о впечатлениях.
да, когда говорят что дока по бусту непонятная - правильно говорят. когда говорят что многое в бусте нелогично - правильно говорят. почему? да потому, что я за ночь прочел всю доку по asio от корки до корки, и не нашел ничего о том, что нельзя выполнять операцию на сокете до тех пор, пока предыдущая не завершилась!
единственное что как-то на это намекает, это цитаты:
Цитата

The program must ensure that the stream performs no other read operations (such as async_read, the stream's async_read_some function, or any other composed operations that perform reads) until this operation completes.

Цитата

The program must ensure that the stream performs no other write operations (such as async_write, the stream's async_write_some function, or any other composed operations that perform writes) until this operation completes.

но не в одной из цитат не говорится о том, что нельзя выполнять запись пока не завершилось чтение, и на оборот! а должно быть выделено красным, и вставлено на каждой странице доки!

эх... держите меня семеро smile 

MAKCimmesphprus, всем сильно благодарен за ваше терпение. всем спасибо. smile 


Это сообщение отредактировал(а) boostcoder - 10.4.2011, 06:58

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  asiotest2.zip 3,68 Kb
PM WWW   Вверх
boostcoder
Дата 10.4.2011, 06:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



но мне все равно не понятно, каким образом операция чтения запущенная одновременно с операцией записи может портить данные которые записываются smile 
PM WWW   Вверх
boostcoder
Дата 10.4.2011, 07:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



удивительно... но использование канала наладилось. 94% smile 
Цитата

per sec requests: 205184
per sec answers : 201890
total requests  : 169479197
total answers   : 169425734

per sec requests: 250922
per sec answers : 235622
total requests  : 169730133
total answers   : 169661370

per sec requests: 181205
per sec answers : 194040
total requests  : 169911338
total answers   : 169855439

per sec requests: 209731
per sec answers : 196663
total requests  : 170121093
total answers   : 170052102



Это сообщение отредактировал(а) boostcoder - 10.4.2011, 07:33
PM WWW   Вверх
MAKCim
Дата 10.4.2011, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  10.4.2011,  06:57 Найти цитируемый пост)
но мне все равно не понятно, каким образом операция чтения запущенная одновременно с операцией записи может портить данные которые записываются 

предположу
start_read->async_read->readed
причем async_read->readed может быть синхронным (если данные уже получены)
в этом случае имеем два последовательных async_write без вызова written


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
phprus
Дата 10.4.2011, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



Цитата(boostcoder @  10.4.2011,  09:28 Найти цитируемый пост)
readed() вызывается когда данные прочитаны. из него я запускаю операцию записи и операцию чтения. и тут ошибка! операцию чтения нужно запускать из хэндлера операции записи. т.е. мало того что в доке намекается на то, что нельзя выполнять две операции записи и чтения одновременно, так оказывается что выполнять чтение пока не завершена запись(и наоборот) тоже нельзя!

А если использовать read и write параллельно с разными, несвязанными данными, то баг тоже воспроизведется? Если да, то это будет по сути баг в ASIO. TCP полнодуплексный протокол и может работать одновременно в обе стороны.

Цитата(boostcoder @  10.4.2011,  10:31 Найти цитируемый пост)
удивительно... но использование канала наладилось. 94%

На каком канале? 100 Мбит/с?
PM MAIL WWW ICQ   Вверх
mes
Дата 10.4.2011, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  05:28 Найти цитируемый пост)
start_write(sock, buf);
   start_read(sock); <<<<<<<<<<<<<<<<<<<<<<

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

Добавлено через 10 минут и 47 секунд
Цитата(boostcoder @  10.4.2011,  05:28 Найти цитируемый пост)
но не в одной из цитат не говорится о том, что нельзя выполнять запись пока не завершилось чтение, и на оборот!
уверен, что можно  smile

Добавлено через 11 минут и 34 секунды
Цитата(boostcoder @  10.4.2011,  05:28 Найти цитируемый пост)
эх... держите меня семеро 

рано эмоции выпустили smile


--------------------
PM MAIL WWW   Вверх
mes
Дата 10.4.2011, 12:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  05:57 Найти цитируемый пост)
но мне все равно не понятно, каким образом операция чтения запущенная одновременно с операцией записи может портить данные которые записываются

данные не портятся, просто приходят не одним куском , а несколькими, на что Вам намекал strlen..

Добавлено через 1 минуту и 55 секунд
а Вы их неправильно интерпретировали неполные блоки, что и служило поводом для исключения..
и еще сервер получив неправильный блок, переправлял его как полный клиенту.. поэтому ошибка только в логах server_out и client_in..

Добавлено через 3 минуты и 30 секунд
т.е. неправильная интерпретация полученных данных сервером,  создавала проблему с логами,
а неправильная интерпретаця клиентом вызывало исключение..

Добавлено через 5 минут и 54 секунды
в общем у Вас получился пример, ловко собравший в себе несколько похожих ошибок, и устранение одной, изменяло ситуацию, но не исправляло ее - именно это и привело к путанице..

Добавлено через 9 минут и 14 секунд
хотя помимо названных причин, вроде еще одна должна быть для полной картины..

Добавлено через 13 минут и 25 секунд
Цитата(boostcoder @  10.4.2011,  05:28 Найти цитируемый пост)
 start_write(sock, buf);
   start_read(sock); <<<<<<<<<<<<<<<<<<<<<<

Цитата(boostcoder @  10.4.2011,  05:28 Найти цитируемый пост)
 так оказывается что выполнять чтение пока не завершена запись(и наоборот) тоже нельзя!

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




--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(phprus @  10.4.2011,  11:38 Найти цитируемый пост)
А если использовать read и write параллельно с разными, несвязанными данными, то баг тоже воспроизведется?

подозреваю что да. тут не данные навязывают ограничения, а asio.

Цитата(phprus @  10.4.2011,  11:38 Найти цитируемый пост)
Если да, то это будет по сути баг в ASIO. TCP полнодуплексный протокол и может работать одновременно в обе стороны.

возможно это действительно не баг, а ограничение реализации asio.
почитай: http://boost.2283326.n4.nabble.com/Multipl...-td2579621.html

Цитата(phprus @  10.4.2011,  11:38 Найти цитируемый пост)
100 Мбит/с?

да.
завтра смогу проверить на 1гбит канале.

Цитата(mes @  10.4.2011,  12:03 Найти цитируемый пост)
у меня подозрения, что Вы не с причиной разобрались, а просто создали благоприятные условия, в которых _баг_  не/реже проявляется.. 
так же как и секундой слипа..

так же, прочтите по ссылке.

Igor R. - это второй человек в поддержке asio. я полагаю весьма компетентный.


Цитата(mes @  10.4.2011,  12:03 Найти цитируемый пост)
уверен, что можно

да, можно. но не при помощи async_write(). нужно писать обертку над сокетом(сегодня этим и займемся ;) ), и в ней использовать socket::async_write_some() и socket::async_read_some(). на сколько я понял из того что по ссылке.

Добавлено через 1 минуту
тест работает почти 7 часов.
PM WWW   Вверх
mes
Дата 10.4.2011, 12:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



кстати комбинация с перемещением start_read во written поможет только для пинг понговского обмена, как у Вас в примере.. 
при нарушении симметрии на чтение запись, опять начнутся проблемы при такой архитектуре..

Добавлено через 2 минуты и 21 секунду
Цитата(boostcoder @  10.4.2011,  11:34 Найти цитируемый пост)
тест работает почти 7 часов. 

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

Добавлено через 2 минуты и 40 секунд
Цитата(boostcoder @  10.4.2011,  11:34 Найти цитируемый пост)
почитай: http://boost.2283326.n4.nabble.com/Multipl...-td2579621.html

сейчас..

Добавлено через 5 минут и 3 секунды
Цитата(boostcoder @  10.4.2011,  11:34 Найти цитируемый пост)
да, можно. но не при помощи async_write(). нужно писать обертку над сокетом(сегодня этим и займемся ;) ), и в ней использовать socket::async_write_some() и socket::async_read_some(). на сколько я понял из того что по ссылке.

нет не поняли smile я говорил что уверен, что нет ограничения, на одновременное использование async_write и async_read .. 
и уверен, что не это служило поводом для багов у Вас в примере..

Добавлено через 7 минут и 17 секунд
Цитата

hand, for async_write, since it is divided in many async_write_some, 

async_read() also performs multiple socket::async_read_some() 

ага так и предполагалось, из за чего ограничение на совместную запись/чтение.. 
но это никак не может служить ограничением на совмещением записи с чтением.. 



--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



mes, насколько я понимаю, одновременное чтение/запись нужно реализовать согласно этому принципу: http://www.boost.org/doc/libs/1_46_0/doc/h...re/reactor.html

Добавлено через 1 минуту и 37 секунд
MAKCim, скажите, sendmsg() и recvmsg() можно использовать одновременно? т.е. с одним сокетом.
PM WWW   Вверх
mes
Дата 10.4.2011, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  12:21 Найти цитируемый пост)
sendmsg() и recvmsg() можно использовать одновременно? т.е. с одним сокетом. 

Цитата(phprus @  10.4.2011,  10:38 Найти цитируемый пост)
TCP полнодуплексный протокол и может работать одновременно в обе стороны.





--------------------
PM MAIL WWW   Вверх
MAKCim
Дата 10.4.2011, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  10.4.2011,  13:21 Найти цитируемый пост)
скажите, sendmsg() и recvmsg() можно использовать одновременно? т.е. с одним сокетом. 

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


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
mes
Дата 10.4.2011, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  12:21 Найти цитируемый пост)
насколько я понимаю, одновременное чтение/запись нужно реализовать согласно этому принципу:

нужно ? можно и как у Вас было, только порядок навести.. 


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



mes, я это видел.
но я никогда такого не проделывал прежде. и тем более с sendmsg() и recvmsg().
я просто хочу понять, это ограничение asio, или OS-API.
PM WWW   Вверх
mes
Дата 10.4.2011, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



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

Добавлено @ 13:32
Цитата(boostcoder @  10.4.2011,  12:31 Найти цитируемый пост)
я просто хочу понять, это ограничение asio, или OS-API. 

что Вы подразумеваете под "это" ?.. 


Это сообщение отредактировал(а) mes - 10.4.2011, 13:32


--------------------
PM MAIL WWW   Вверх
MAKCim
Дата 10.4.2011, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



 smile 
еще раз убедился в том, как С++ на примере boost'а усложняет жизнь
было бы что-то другое, можно было посмотреть реализацию и выяснить все вопросы
лезть же в boost удовольствие сомнительное ;)


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
boostcoder
Дата 10.4.2011, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  10.4.2011,  13:30 Найти цитируемый пост)
да
входной и выходной буферы сокета независимы
я даже больше скажу, можно одновременно из разных потоков делать sendmsg()

понял. спасибо.

значит нужно автора asio закидать письмами с четкими вопросами.

Цитата(mes @  10.4.2011,  13:30 Найти цитируемый пост)
можно и как у Вас было, только порядок навести..

что конкретно нужно изменить?
я тоже понимаю что что-то не так. но согласно приведенной ссылке, во втором посте есть такое:
Цитата

Of course, you still can run async_read and async_write together for one connection. 

мне не кажется, что тут говорится о том, что можно читать и писать одновременно?
PM WWW   Вверх
mes
Дата 10.4.2011, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  12:36 Найти цитируемый пост)
мне не кажется, что тут говорится о том, что можно читать и писать одновременно? 

так Вам все об этом говорят smile что нет на это ограничений smile



--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  10.4.2011,  13:33 Найти цитируемый пост)
еще раз убедился в том, как С++ на примере boost'а усложняет жизнь
было бы что-то другое, можно было посмотреть реализацию и выяснить все вопросы
лезть же в boost удовольствие сомнительное ;)

но не писать же свою реализацию сокетов со всем вытекающим...

я еще неделю назад подумывал использовать POCO. но это не удобно, тянуть в проект еще что-то. у меня проект полностью написан с использованием буста. ну еще openssl...


Это сообщение отредактировал(а) boostcoder - 10.4.2011, 13:45
PM WWW   Вверх
mes
Дата 10.4.2011, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  12:36 Найти цитируемый пост)
значит нужно автора asio закидать письмами с четкими вопросами.

пока вопросы возникшие в этой теме освещены документацией... не смотря на то, что она действительно скудная.. 
;)

Добавлено через 41 секунду
Цитата(boostcoder @  10.4.2011,  12:39 Найти цитируемый пост)
но не писать же свою реализацию сокетов со всем вытекающим...

asio Вас уже испугало ?  smile  smile

Добавлено через 5 минут и 47 секунд
Цитата(boostcoder @  10.4.2011,  12:36 Найти цитируемый пост)
что конкретно нужно изменить?

при чтении не делать start_write,
a добавлять в очередь, из которой забирать по writen..

Добавлено через 8 минут и 47 секунд
Цитата(MAKCim @  10.4.2011,  12:33 Найти цитируемый пост)
еще раз убедился в том, как С++ на примере boost'а усложняет жизнь

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


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  10.4.2011,  12:19 Найти цитируемый пост)
и еще сервер получив неправильный блок, переправлял его как полный клиенту.. поэтому ошибка только в логах server_out и client_in..

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

Добавлено через 1 минуту и 50 секунд
Цитата(mes @  10.4.2011,  13:39 Найти цитируемый пост)
при чтении не делать start_write,
a добавлять в очередь, из которой забирать по writen..

переделаю. не вопрос.
PM WWW   Вверх
mes
Дата 10.4.2011, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  12:49 Найти цитируемый пост)
сервер ни разу не обнаружил несоответствие во входящих данных.

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

Цитата(boostcoder @  10.4.2011,  12:49 Найти цитируемый пост)
переделаю. не вопрос. 

и должен стать порядок и на сервере smile




--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  10.4.2011,  13:30 Найти цитируемый пост)
правда насчет атомарности записи данных (данные каждого sendmsg() запишутся непрерывно) не уверен

хм.. а это очень любопытно..

Добавлено @ 14:15
Цитата(mes @  10.4.2011,  13:39 Найти цитируемый пост)
добавлять в очередь, из которой забирать по writen..

а если очередь пуста, то по какому событию делать проверку/перезапуск отправки из очереди?

Добавлено @ 14:16

ужо 2.2 мильярда)

total requests  : 2212348580
total answers   : 2212269496


Добавлено @ 14:17
Цитата(mes @  10.4.2011,  13:39 Найти цитируемый пост)
при чтении не делать start_write,
a добавлять в очередь, из которой забирать по writen..

хотя.. не вижу принципиальной разницы.. в чем она?

Добавлено @ 14:22
Цитата(MAKCim @  10.4.2011,  13:30 Найти цитируемый пост)
правда насчет атомарности записи данных (данные каждого sendmsg() запишутся непрерывно) не уверен

а разве sendmsg() и recvmsg() не используют writev() и readv() ?
хотя ни в одной из моих книжек по программированию для линукс, не говорится об атомарности записи/чтения... погуглю..

Это сообщение отредактировал(а) boostcoder - 10.4.2011, 14:31
PM WWW   Вверх
mes
Дата 10.4.2011, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  13:13 Найти цитируемый пост)
хотя.. не вижу принципиальной разницы.. в чем она?

представьте ситуацию когда на два чтения должна происходить одна запись smile

Добавлено через 1 минуту и 46 секунд
Цитата(boostcoder @  10.4.2011,  13:13 Найти цитируемый пост)
а если очередь пуста, то по какому событию делать проверку/перезапуск отправки из очереди?

добавить флаг.. если очередь пуста и нет активной write, то после добавления стартовать ее, иначе просто добавлять.. 



--------------------
PM MAIL WWW   Вверх
phprus
Дата 10.4.2011, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 129
Регистрация: 22.8.2006

Репутация: 1
Всего: 3



Цитата(boostcoder @  10.4.2011,  15:34 Найти цитируемый пост)
да.
завтра смогу проверить на 1гбит канале.

Напиши, пожалуйста, результаты (% использования канала) и RTT канала.
PM MAIL WWW ICQ   Вверх
boostcoder
Дата 10.4.2011, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



phprus, ок. отпишусь.

mes, вот что получилось. изменил только сервер. оно даже работает smile
Код


#include <iostream>
#include <queue>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/lexical_cast.hpp>

#include "header.hpp"

/***************************************************************************/

struct queue {
   void push(char* ptr) {
      boost::mutex::scoped_lock locker(mutex);
      queue.push(ptr);
   }

   char* pop() {
      boost::mutex::scoped_lock locker(mutex);
      if ( queue.empty() ) return 0;
      char* ptr = queue.front();
      queue.pop();
      return ptr;
   }

   bool empty() const {
      boost::mutex::scoped_lock locker(mutex);
      return queue.empty();
   }

private:
   mutable boost::mutex mutex;
   std::queue<char*> queue;
} q;

bool in_process = false;

/***************************************************************************/

void start_write(boost::asio::ip::tcp::socket&);

void writen(boost::asio::ip::tcp::socket&,
            char*,
            const boost::system::error_code&,
            size_t);

void start_read(boost::asio::ip::tcp::socket&);

void readed(boost::asio::ip::tcp::socket&,
            char*,
            const boost::system::error_code&,
            size_t);

/***************************************************************************/

void start_write(boost::asio::ip::tcp::socket& sock) {
   if ( char* buf = q.pop() ) {
      boost::asio::async_write(
         sock,
         boost::asio::buffer(buf, send_buffer_size),
         boost::bind(
            &writen,
            boost::ref(sock),
            buf,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
         )
      );
   }
}

void writen(boost::asio::ip::tcp::socket& sock,
            char* buf,
            const boost::system::error_code& e,
            size_t wr)
{
   if ( e ) {
      throw std::runtime_error("writen(): " + e.message());
   }

   if ( wr != send_buffer_size ) {
      std::cout
      << "writen(): " << buf << ", len: " << wr << std::endl;
   }

   delete[] buf;

   if ( !q.empty() ) {
      in_process = true;
      start_write(sock);
   } else {
      in_process = false;
   }
}

/***************************************************************************/

void start_read(boost::asio::ip::tcp::socket& sock) {
   char* buf = new char[recv_buffer_size];
   boost::asio::async_read(
      sock,
      boost::asio::buffer(buf, recv_buffer_size),
      boost::bind(
         &readed,
         boost::ref(sock),
         buf,
         boost::asio::placeholders::error,
         boost::asio::placeholders::bytes_transferred
      )
   );
}

void readed(boost::asio::ip::tcp::socket& sock,
            char* buf,
            const boost::system::error_code& e,
            size_t rd)
{
   if ( e ) {
      throw std::runtime_error("read handler: " + e.message());
   }

   if ( rd != recv_buffer_size ) {
      std::cout
      << "readed(): " << buf << ", len: " << rd << std::endl;
   }

   static boost::uint64_t idx = 0;
   boost::uint64_t tmp = atoll(buf);
   if ( idx != tmp ) {
      fprintf(stdout, "expected: %12llu, get: %12llu, buf: %s", idx, tmp, buf);
      fflush(stdout);
   }

   ++idx;

   q.push(buf);

   if ( !in_process ) {
      in_process = true;
      start_write(sock);
   }
   
   start_read(sock);
}

/***************************************************************************/

int main(int argc, char** argv) {
   if ( argc != 3 ) {
      std::cout << "server ip port" << std::endl;
      return 0;
   }

   if ( init_wrappers() ) {
      return -1;
   }
   try {
      std::string ip = argv[1];
      boost::uint16_t port = atoi(argv[2]);
/*
      dbg::in = fopen("server_in.log", "wb");
      dbg::out= fopen("server_out.log", "wb");
      if ( !dbg::out || !dbg::in ) {
         std::cout << "can`t open file!" << std::endl;
         return 1;
      }
*/
      boost::asio::ip::tcp::endpoint endpoint(
         boost::asio::ip::address::from_string(ip), port
      );

      boost::asio::io_service ios;
      boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);
      boost::asio::ip::tcp::socket socket(ios);

      acceptor.accept(socket);
      std::cout << "new connection from: " << socket.remote_endpoint().address().to_string() << std::endl;

      boost::asio::socket_base::non_blocking_io non_blocking_io(true);
      socket.io_control(non_blocking_io);

      start_read(socket);
      
      ios.run();
   } catch ( const std::exception& e ) {
      std::cout << "(exception): " << e.what() << std::endl;
   }
/*
   fclose(dbg::in);
   fclose(dbg::out);
*/
}

/***************************************************************************/



PM WWW   Вверх
boostcoder
Дата 10.4.2011, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



зы
нехочу постоянно помнить о познаных ограничениях. хочу обертку над сокетом. умную. удобную.

PM WWW   Вверх
mes
Дата 10.4.2011, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 1
Всего: 250



Цитата(boostcoder @  10.4.2011,  17:02 Найти цитируемый пост)
вот что получилось. изменил только сервер.оно даже работает. smile

Цитата(mes @  10.4.2011,  12:56 Найти цитируемый пост)
значит тогда клиент в порядке.. получается, что рубились только на сервере.. 

smile
Цитата(boostcoder @  10.4.2011,  17:20 Найти цитируемый пост)
нехочу постоянно помнить о познаных ограничениях. хочу обертку над сокетом. умную. удобную. 

а разве asiо не предлагает ? ту которую Вы раньше применяли, в той длинной теме..

Добавлено @ 18:58
оглянувшись назад, можно оценить насколько пророчески были слова MAKCim
Цитата(MAKCim @  29.3.2011,  13:28 Найти цитируемый пост)
Цитата(boostcoder)

насколько это возможно утверждать на приведенном коде - да. просто код реально мегапрост, чтоб где-то мог закрасться баг. если конечно это не баг asio. в чем сомневаюсь.. 


в этом большая ошибка
я много раз на это же полагался
а в итоге как раз в мегапростом коде и был баг ;)

 smile  smile 


Это сообщение отредактировал(а) mes - 10.4.2011, 18:58


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 10.4.2011, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(mes @  10.4.2011,  18:55 Найти цитируемый пост)
а разве asiо не предлагает ? ту которую Вы раньше применяли

что-то не помню.
ладно, тему можно закрывать. а по поводу обертки создам новую тему. в общем разделе smile

Добавлено через 52 секунды
Цитата(mes @  10.4.2011,  18:55 Найти цитируемый пост)
оглянувшись назад, можно оценить насколько пророчески были слова MAKCim

это да.
не в первый раз раз себя на таком ловлю... эх..
PM WWW   Вверх
MAKCim
Дата 10.4.2011, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  10.4.2011,  14:13 Найти цитируемый пост)
а разве sendmsg() и recvmsg() не используют writev() и readv() ?

нет

Добавлено через 4 минуты и 45 секунд
boostcoder
сейчас, кстати посмотрел код ядра и немного офигел
http://tomoyo.sourceforge.jp/cgi-bin/lxr/s...ipv4/tcp.c#L914
что-то я не вижу локов
это наводит на мысль, что в linux'е лучше не пытаться писать в сокет из более одного потока без своих локов

Добавлено через 7 минут и 56 секунд
 smile 
Цитата(boostcoder @  10.4.2011,  18:59 Найти цитируемый пост)
не в первый раз раз себя на таком ловлю... эх.. 

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

просто когда много раз об это спотыкаешься, начинаешь относится к себе более критически дабы решить проблему быстрее


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
boostcoder
Дата 10.4.2011, 19:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  10.4.2011,  19:04 Найти цитируемый пост)
психика у нас устроена таким образом, что мы априори не хотим признавать, что ошибка может быть у нас

это правда smile 
PM WWW   Вверх
MAKCim
Дата 10.4.2011, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



короче я нагнал
лок там есть в самом верху, я проглядел, паника отменяется smile 


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
boostcoder
Дата 10.4.2011, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(MAKCim @  10.4.2011,  19:04 Найти цитируемый пост)
нет

в структуре msghdr есть такой член:
Код

struct msghdr {
    ...
    struct iovec *msg_iov; <<<<<<<<<<<<<<
    ...
};


эта же структура используется и для writev(). вот я и подумал, что в sendmsg() используется writev() дабы не плодить код.

Цитата(MAKCim @  10.4.2011,  19:04 Найти цитируемый пост)
сейчас, кстати посмотрел код ядра и немного офигел
http://tomoyo.sourceforge.jp/cgi-bin/lxr/s...ipv4/tcp.c#L914
что-то я не вижу локов
это наводит на мысль, что в linux'е лучше не пытаться писать в сокет из более одного потока без своих локов

ну вот, еще полезная информация.

Добавлено через 52 секунды
Цитата(MAKCim @  10.4.2011,  19:24 Найти цитируемый пост)
лок там есть в самом верху

это он? :
Цитата

lock_sock(sk);

PM WWW   Вверх
MAKCim
Дата 10.4.2011, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 6
Всего: 207



Цитата(boostcoder @  10.4.2011,  19:24 Найти цитируемый пост)
это он? :

ага


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
boostcoder
Дата 11.4.2011, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



phprus, привет.
RTT = 50-54ms

в клиенте и сервере пришлось размер массивов увеличить до 10к, т.к. они съедали ядро из-за огромного кол-ва аллокаций и прочего.
использование канала ~82%
т.е. уверенно 800 мбит.

Это сообщение отредактировал(а) boostcoder - 11.4.2011, 11:04
PM WWW   Вверх
boostcoder
Дата 11.4.2011, 18:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



что-то заблудился..

не понимаю, почему этот код бажил -
Цитата(boostcoder @  10.4.2011,  05:38 Найти цитируемый пост)
   start_write(sock, buf);
   start_read(sock);

а код с очередью нет? smile

Добавлено через 2 минуты
ааа.. у меня новая запись запускалась еще до того как предыдущая завершилась smile 
PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.4071 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.