Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 82, средняя оценка - 4.87
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
#1

Баг asio? или баг TCP стека? - C++

08.04.2011, 14:50. Просмотров 9856. Ответов 5
Метки нет (Все метки)

всем привет.

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

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

Размер: 3.8 Кб

на стороне сервера, так же, сохраняю принятые массивы.
но тут, массив приходит искаженным:
Название: 2.png
Просмотров: 604

Размер: 4.1 Кб

от снифф этого участка, tcpdump`ом, на стороне клиента:
Баг asio? или баг TCP стека?

а это на стороне сервера:
Название: 4.png
Просмотров: 595

Размер: 3.7 Кб



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

еще более странно то, что если третьим аргументом клиенту передать "1" - то между асинхронными записями будет использоваться sleep() в 1мс - что полностью решает проблему. но такое решение не подходит.

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

клиент:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#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:%8dn", 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/15c1e7...1eebe7e08564a7

сервер:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#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/0a8e2c...31f28c46ddf9e2

общий хидер:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#ifndef _header_hpp_included_
#define _header_hpp_included_
 
#include <iostream>
#include <cstdio>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.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/9f9e4f...d44f5074181215

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

зы
во вложении, архив с исходниками и Makefile`ом. проверено на gcc-linux и на mingw32.
asiotest2.zip
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.04.2011, 14:50     Баг asio? или баг TCP стека?
Посмотрите здесь:

std::regex : баг на сайте или баг компилятора? - C++
http://en.cppreference.com/w/cpp/regex/regex_match этот код выкидывает throw... Добавлено через 35 секунд компилятор gcc 4.8

Баг или фича - C++
решил проверить на своем VS 2008 присвоение в сравнении написал char buf; char *buf1; if(buf1=buf) все прошло никакого...

Баг или особенность? - C++ Builder
Делаю проект на 6-м билдере и внезапно столкнулся с таким недоразумением. Со включенным build with runtime packeges все работает...

баг или что-то другое? - Visual C++
вот код: enum SexType {female, male}; struct PersonStruct { char name; int age; SexType sex; }; void...

Ошибка или баг в Dev C++? - C++
помогите разобраться: вот простой код #include &lt;cstdlib&gt; #include &lt;iostream&gt; using namespace std; class card { public: ...

Баг компилятора? Или я чего то не догоняю? - C++
Компилил в 2008 студии. Вопрос: ПОЧЕМУ ЭТОТ КОД КОМПИЛИРУЕТСЯ? class Bee { private: template&lt;class Foo2&gt; Bee&amp;...

Ввод/вывод баг или нет? - C++
#include &lt;iostream&gt; #include &lt;iterator&gt; #include &lt;string&gt; using namespace std; ostream_iterator&lt;string&gt; oo(cout); ...

XE3 баг или кривые руки? - C++ Builder
Проблемы с указателем таблицы, дойдя до последней записи, внезапно появляется ещё десяток левых записей и список продолжается)) Даже создав...

Ошибка или баг Visual Studio 2015? - C++
Кто сталкивался с проблемой когда после сборки программы, зависает Visual? Даже пустой проект не может запустить, хотя раньше запускал....

помогите определить баг или недочёт в программе. - C++
Задача ввести с клавиатуры массив и вывести на экран наибольший его элемент. Проблема заключается в if когда s&lt;mas он всё время...

баг компилятора, или беда с типами данных? - C++ Builder
привет) есть задача, где нужно проверить, равна ли сумма чисел единице... проще простого не правда ли, но вот что у меня получаеться: ...

Баг VS или как? Функция в многофайловом приложении - C++
#include &quot;function.h&quot; int main(){ LoadFileToStack(); cout &lt;&lt; endl; st return 0; } void LoadFileToStack() ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
08.04.2011, 15:29  [ТС]     Баг asio? или баг TCP стека? #2
при помощи strace обнаружил, что для ввода-вывода используются sendmsg() и recvmsg(), а не send() и recv() как предполагал.
g_u_e_s_t
1258 / 649 / 30
Регистрация: 06.02.2011
Сообщений: 1,724
08.04.2011, 16:15     Баг asio? или баг TCP стека? #3
По поводу sendxxx - по крайней мере на линуксе send() и sendto() это обертки вокруг sendmsg()
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
08.04.2011, 17:28  [ТС]     Баг asio? или баг TCP стека? #4
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
на линуксе send() и sendto() это обертки вокруг sendmsg()
ну хз... pthrace вообще говорит что таких функций не вызывается.
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
08.04.2011, 22:48  [ТС]     Баг asio? или баг TCP стека? #5
вот что еще странно...
в один прекрасный момент, сервер принимает это:
Баг asio? или баг TCP стека?

в первой строке сверху - все хорошо.
во второй и третьей строке, вместо завершающего нуля, вставлен символ c
в четвертой строке, символа c вначале, попросту нет.


у кого-то есть мысли по этому поводу?
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
09.04.2011, 20:03  [ТС]     Баг asio? или баг TCP стека? #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
баг распознан и ликвидирован.
как оказалось, это вовсе не баг, а неправильное использование функций asio.

в примечании к async_write() есть такое:
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.
я все время под этим понимал то, что одна из перечисленных функций не должна вызываться одновременно из другого потока, пока эта на завершиться.
а оказалось, что их нельзя вызывать до тех пор, пока не будет вызван хэндлер предыдущей.

всем спасибо.
Yandex
Объявления
09.04.2011, 20:03     Баг asio? или баг TCP стека?
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru