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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> баг asio? или баг TCP стека? 
V
    Опции темы
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   Вверх
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.1205 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.