質問するログイン新規登録

質問編集履歴

4

並べ替え

2017/11/07 16:40

投稿

Unity-chan
Unity-chan

スコア20

title CHANGED
File without changes
body CHANGED
@@ -202,6 +202,55 @@
202
202
  return 0;
203
203
  }
204
204
  ```
205
+
206
+ ###試したこと
207
+ 参考URLのようにReceiveTCP()をOnConnect()内で呼び出すと問題なく動作するのですが,今後連続でデータ待機を行う場合に毎回Connectを行う必要が出てくるので可能であればOnConnectからReceiveTCPを呼び出す方法は避けたいと考えています.
208
+
209
+ ###補足情報(言語/FW/ツール等のバージョンなど)
210
+ Visual Studio 2017
211
+ Boost 1.65.1
212
+
213
+ ###**追記**
214
+ ###**受信ソース(修正箇所)**
215
+ ```C++
216
+ // 接続が完了したか(async_accept用で、引数は固定)
217
+ void OnAccept(const boost::system::error_code& error)
218
+ {
219
+ if (error)
220
+ cout << "connect failed : " + error.message() << endl;
221
+ else
222
+ cout << "Success connection." << endl;
223
+
224
+ //-----編集箇所--------------------------
225
+ ReceiveTCP();
226
+ //-----編集箇所--------------------------
227
+ }
228
+
229
+
230
+ // 受信が成功したか(async_read用で,引数は固定)
231
+ void OnReceive(const boost::system::error_code& error, size_t bytes_transferred)
232
+ {
233
+ if (error && error != asio::error::eof)
234
+ cout << "receive failed: " << error.message() << endl;
235
+ else {
236
+ // 受信したデータをchar*に変換
237
+ const char* data = asio::buffer_cast<const char*>(receive_buff_.data());
238
+ lastData = const_cast<char*>(data);
239
+ cout << lastData << endl;
240
+
241
+ receive_buff_.consume(receive_buff_.size());
242
+
243
+ //-----編集箇所--------------------------
244
+ if (lastData[0] != 'e') {
245
+ cout << "endしないよ:" << lastData << endl;
246
+ ReceiveTCP();
247
+ }
248
+ else
249
+ cout << "endするよ" << endl;
250
+ //-----編集箇所--------------------------
251
+ }
252
+ }
253
+ ```
205
254
  ###**送信ソース**
206
255
 
207
256
  参考URLのソースから,他ソースコードから送信したい文字列を指定できるように変更した.
@@ -409,55 +458,6 @@
409
458
  return 0;
410
459
  }
411
460
  ```
412
- ###試したこと
413
- 参考URLのようにReceiveTCP()をOnConnect()内で呼び出すと問題なく動作するのですが,今後連続でデータ待機を行う場合に毎回Connectを行う必要が出てくるので可能であればOnConnectからReceiveTCPを呼び出す方法は避けたいと考えています.
414
-
415
- ###補足情報(言語/FW/ツール等のバージョンなど)
416
- Visual Studio 2017
417
- Boost 1.65.1
418
-
419
- ###**追記**
420
- ###受信ソース(修正箇所)
421
- ```C++
422
- // 接続が完了したか(async_accept用で、引数は固定)
423
- void OnAccept(const boost::system::error_code& error)
424
- {
425
- if (error)
426
- cout << "connect failed : " + error.message() << endl;
427
- else
428
- cout << "Success connection." << endl;
429
-
430
- //-----編集箇所--------------------------
431
- ReceiveTCP();
432
- //-----編集箇所--------------------------
433
- }
434
-
435
-
436
- // 受信が成功したか(async_read用で,引数は固定)
437
- void OnReceive(const boost::system::error_code& error, size_t bytes_transferred)
438
- {
439
- if (error && error != asio::error::eof)
440
- cout << "receive failed: " << error.message() << endl;
441
- else {
442
- // 受信したデータをchar*に変換
443
- const char* data = asio::buffer_cast<const char*>(receive_buff_.data());
444
- lastData = const_cast<char*>(data);
445
- cout << lastData << endl;
446
-
447
- receive_buff_.consume(receive_buff_.size());
448
-
449
- //-----編集箇所--------------------------
450
- if (lastData[0] != 'e') {
451
- cout << "endしないよ:" << lastData << endl;
452
- ReceiveTCP();
453
- }
454
- else
455
- cout << "endするよ" << endl;
456
- //-----編集箇所--------------------------
457
- }
458
- }
459
- ```
460
-
461
461
  実行結果
462
462
  それぞれ1文字ずつ[a, b, c, d, e]と送信した場合
463
463
  ![イメージ説明](addcdf1c58916b195e3101ccd2141703.png)

3

送信ソース追加

2017/11/07 16:40

投稿

Unity-chan
Unity-chan

スコア20

title CHANGED
File without changes
body CHANGED
@@ -1,15 +1,16 @@
1
- ###前提・実現したいこと
1
+ ###**前提・実現したいこと**
2
+
2
3
   非同期で送信されるデータを,連続で受け取るプログラムの構築を目指しています.
3
4
  具体的には「スレッドでデータ待機する→受け取る→表示する→データ待機する・・・」という処理を実現したいと考えています.
4
5
   またMain関数からはAsioのライブラリが見えないように構築したいと考えています.
5
- ###現状
6
+ ###**現状**
6
7
  BoostライブラリのAsioを用いて構築したコードを確認するために,送信したデータを表示して終了するプログラムを構築しました.(参考:https://boostjp.github.io/tips/network/tcp.html)
7
- ###発生している問題・エラーメッセージ
8
+ ###**発生している問題・エラーメッセージ**
8
9
  実行すると以下のエラーメッセージが表示されます.(IPReceiveData.cppのOnReceive関数)
9
10
  ```
10
11
  receive failed: 供給されたファイルハンドルが無効です.
11
12
  ```
12
-
13
+ ###**受信ソース**
13
14
  ###IPReceiveData.h
14
15
  ```c++
15
16
  #ifndef __IPConnect_h__
@@ -201,6 +202,213 @@
201
202
  return 0;
202
203
  }
203
204
  ```
205
+ ###**送信ソース**
206
+
207
+ 参考URLのソースから,他ソースコードから送信したい文字列を指定できるように変更した.
208
+ ###IPSendData.h
209
+ ```C++
210
+ #ifndef __IPConnect_h__
211
+ #define __IPConnect_h__
212
+
213
+
214
+ enum TransportProtocol {
215
+ TP_TCP = 1,
216
+ TP_UDP = 0,
217
+ };
218
+
219
+ class IPSending {
220
+ public:
221
+ // TCPかUDPか選択(最初に選択すれば、初期化やメッセージ送信ではTCPUDP区別なく関数を使える)
222
+ IPSending(TransportProtocol isTcp);
223
+ ~IPSending();
224
+
225
+ void ipsInitialize(char* ipAddress, char *portNum);
226
+
227
+ void ipsSendMSG(char* msg);
228
+
229
+ private:
230
+ class IPSend_impl* ips_impl;
231
+ };
232
+
233
+ #endif
234
+ ```
235
+ ###IPSendData.cpp
236
+ ```C++
237
+
238
+ #define BOOST_COROUTINES_NO_DEPRECATION_WARNING // asioはcoroutine2をサポートしていないので警告を消す
239
+ #define PIMP(x) ips_impl->x
240
+
241
+ #include <iostream>
242
+ #include <memory>
243
+ #include <boost/asio.hpp>
244
+ #include <boost/bind.hpp>
245
+ #include <boost/asio/spawn.hpp>
246
+ #include "IPSendData.h"
247
+
248
+ namespace asio = boost::asio;
249
+ using asio::ip::tcp;
250
+ using asio::ip::udp;
251
+ using std::cout;
252
+ using std::endl;
253
+ using std::string;
254
+ using std::shared_ptr;
255
+
256
+
257
+
258
+ class IPSend_impl {
259
+ private:
260
+ tcp::socket socketTCP; // TCP
261
+ udp::socket socketUDP; // UDP
262
+ udp::resolver resolver; // UDP
263
+ asio::strand strand; // spawn
264
+ udp::endpoint receiver_endpoint;
265
+ string sendData; // SendTCPでしか使わないが、使用する前にスコープ外へ出て消えてしまうので外
266
+
267
+
268
+ // 接続が完了したか(async_connect用で、引数は固定)
269
+ void OnConnect(const boost::system::error_code& error)
270
+ {
271
+ if (error)
272
+ throw "connect failed : " + error.message();
273
+ else
274
+ cout << "connect correct!" << endl;
275
+ }
276
+
277
+ void OnSend(const boost::system::error_code& error, size_t bytes_transferred)
278
+ {
279
+ if (error)
280
+ throw "send failed: " + error.message();
281
+ else
282
+ cout << "send correct!" << endl;
283
+ }
284
+
285
+
286
+ public:
287
+ asio::io_service& ioService;
288
+ const bool isTCP;
289
+
290
+
291
+ // TCPとUDPを指定して初期化するコンストラクタ
292
+ IPSend_impl(asio::io_service& ioService, TransportProtocol isTcp)
293
+ : ioService (ioService),
294
+ resolver (ioService),
295
+ strand (ioService),
296
+ socketTCP (ioService),
297
+ socketUDP (ioService),
298
+ isTCP (isTcp){}
299
+
300
+ // デストラクタ
301
+ ~IPSend_impl() {
302
+ }
303
+
304
+
305
+ // TCPの接続要求を行う
306
+ void ConnectTCP(char *ipAddress, char *portNum) {
307
+ // 接続するIPとポート番号を設定する
308
+ auto address(
309
+ tcp::endpoint(
310
+ asio::ip::address::from_string(ipAddress), atoi(portNum)));
311
+
312
+ // 接続時に実行するコールバック関数を設定する
313
+ auto cbOnConnect(
314
+ boost::bind(&IPSend_impl::OnConnect, this,
315
+ asio::placeholders::error));
316
+
317
+ // 上記で宣言したアドレスとコールバック関数を登録する
318
+ socketTCP.async_connect(address, cbOnConnect);
319
+ }
320
+
321
+ // UDPの接続要求を行う
322
+ void ConnectUDP(char *ipAddress, char *portNum) {
323
+ auto query(udp::resolver::query(udp::v4(), ipAddress, portNum));
324
+ receiver_endpoint = *resolver.resolve(query);
325
+
326
+ socketUDP.open(udp::v4());
327
+ }
328
+
329
+
330
+ // TCPでメッセージを送信
331
+ void SendTCP(char *msg)
332
+ {
333
+ sendData = msg;
334
+
335
+ // 接続後に呼ばれる関数(今回は成否出力)
336
+ auto cbOnSend(
337
+ boost::bind(&IPSend_impl::OnSend, this,
338
+ asio::placeholders::error,
339
+ asio::placeholders::bytes_transferred));
340
+
341
+
342
+ // ソケット、上記で宣言した送信データとコールバック関数を登録する
343
+ asio::async_write(
344
+ socketTCP,
345
+ asio::buffer(sendData),
346
+ cbOnSend);
347
+ }
348
+
349
+
350
+ // メッセージ送信
351
+ void SendUDP(char *msg){
352
+ }
353
+ };
354
+
355
+
356
+
357
+ // IP通信の初期化を行う
358
+ IPSending::IPSending(TransportProtocol isTcp) {
359
+ auto ioService = new asio::io_service;
360
+ ips_impl = new IPSend_impl(*ioService, isTcp);
361
+ }
362
+
363
+ IPSending::~IPSending() {
364
+ delete ips_impl;
365
+ cout << "Finalize IPSending." << endl;
366
+ }
367
+
368
+
369
+ // TCP通信の初期化
370
+ void IPSending::ipsInitialize(char *ipAddress, char *portNum) {
371
+ if (ips_impl->isTCP)
372
+ PIMP(ConnectTCP(ipAddress, portNum));
373
+ else
374
+ PIMP(ConnectUDP(ipAddress, portNum));
375
+ }
376
+
377
+ void IPSending::ipsSendMSG(char *msg) {
378
+ if (PIMP(isTCP)) {
379
+ PIMP(SendTCP(msg));
380
+ PIMP(ioService.run());
381
+ }
382
+ else
383
+ PIMP(SendUDP(msg));
384
+ }
385
+ ```
386
+ ###Main.cpp
387
+ ```C++
388
+ #include <iostream>
389
+ #include "IPSendData.h"
390
+ #define __test__
391
+
392
+ int main() {
393
+ char test[30];
394
+
395
+ IPSending ipSending(TP_TCP);
396
+
397
+ ipSending.ipsInitialize("127.0.0.1", "31400");
398
+
399
+ while (true) {
400
+ std::cout << "文字を入力してください:";
401
+ scanf_s(aaa, 10);
402
+
403
+ ipSending.ipsSendMSG(aaa);
404
+
405
+ if (aaa[0] == 'e')
406
+ break;
407
+ }
408
+
409
+ return 0;
410
+ }
411
+ ```
204
412
  ###試したこと
205
413
  参考URLのようにReceiveTCP()をOnConnect()内で呼び出すと問題なく動作するのですが,今後連続でデータ待機を行う場合に毎回Connectを行う必要が出てくるので可能であればOnConnectからReceiveTCPを呼び出す方法は避けたいと考えています.
206
414
 
@@ -208,7 +416,8 @@
208
416
  Visual Studio 2017
209
417
  Boost 1.65.1
210
418
 
211
- ###追記
419
+ ###**追記**
420
+ ###受信ソース(修正箇所)
212
421
  ```C++
213
422
  // 接続が完了したか(async_accept用で、引数は固定)
214
423
  void OnAccept(const boost::system::error_code& error)

2

追記の改善

2017/11/06 09:07

投稿

Unity-chan
Unity-chan

スコア20

title CHANGED
File without changes
body CHANGED
@@ -247,4 +247,8 @@
247
247
  //-----編集箇所--------------------------
248
248
  }
249
249
  }
250
- ```
250
+ ```
251
+
252
+ 実行結果
253
+ それぞれ1文字ずつ[a, b, c, d, e]と送信した場合
254
+ ![イメージ説明](addcdf1c58916b195e3101ccd2141703.png)

1

プログラムの改善

2017/11/06 06:03

投稿

Unity-chan
Unity-chan

スコア20

title CHANGED
File without changes
body CHANGED
@@ -206,4 +206,45 @@
206
206
 
207
207
  ###補足情報(言語/FW/ツール等のバージョンなど)
208
208
  Visual Studio 2017
209
- Boost 1.65.1
209
+ Boost 1.65.1
210
+
211
+ ###追記
212
+ ```C++
213
+ // 接続が完了したか(async_accept用で、引数は固定)
214
+ void OnAccept(const boost::system::error_code& error)
215
+ {
216
+ if (error)
217
+ cout << "connect failed : " + error.message() << endl;
218
+ else
219
+ cout << "Success connection." << endl;
220
+
221
+ //-----編集箇所--------------------------
222
+ ReceiveTCP();
223
+ //-----編集箇所--------------------------
224
+ }
225
+
226
+
227
+ // 受信が成功したか(async_read用で,引数は固定)
228
+ void OnReceive(const boost::system::error_code& error, size_t bytes_transferred)
229
+ {
230
+ if (error && error != asio::error::eof)
231
+ cout << "receive failed: " << error.message() << endl;
232
+ else {
233
+ // 受信したデータをchar*に変換
234
+ const char* data = asio::buffer_cast<const char*>(receive_buff_.data());
235
+ lastData = const_cast<char*>(data);
236
+ cout << lastData << endl;
237
+
238
+ receive_buff_.consume(receive_buff_.size());
239
+
240
+ //-----編集箇所--------------------------
241
+ if (lastData[0] != 'e') {
242
+ cout << "endしないよ:" << lastData << endl;
243
+ ReceiveTCP();
244
+ }
245
+ else
246
+ cout << "endするよ" << endl;
247
+ //-----編集箇所--------------------------
248
+ }
249
+ }
250
+ ```