質問編集履歴

4

並べ替え

2017/11/07 16:40

投稿

Unity-chan
Unity-chan

スコア20

test CHANGED
File without changes
test CHANGED
@@ -406,6 +406,104 @@
406
406
 
407
407
  ```
408
408
 
409
+
410
+
411
+ ###試したこと
412
+
413
+ 参考URLのようにReceiveTCP()をOnConnect()内で呼び出すと問題なく動作するのですが,今後連続でデータ待機を行う場合に毎回Connectを行う必要が出てくるので可能であればOnConnectからReceiveTCPを呼び出す方法は避けたいと考えています.
414
+
415
+
416
+
417
+ ###補足情報(言語/FW/ツール等のバージョンなど)
418
+
419
+ Visual Studio 2017
420
+
421
+ Boost 1.65.1
422
+
423
+
424
+
425
+ ###**追記**
426
+
427
+ ###**受信ソース(修正箇所)**
428
+
429
+ ```C++
430
+
431
+ // 接続が完了したか(async_accept用で、引数は固定)
432
+
433
+ void OnAccept(const boost::system::error_code& error)
434
+
435
+ {
436
+
437
+ if (error)
438
+
439
+ cout << "connect failed : " + error.message() << endl;
440
+
441
+ else
442
+
443
+ cout << "Success connection." << endl;
444
+
445
+
446
+
447
+ //-----編集箇所--------------------------
448
+
449
+ ReceiveTCP();
450
+
451
+ //-----編集箇所--------------------------
452
+
453
+ }
454
+
455
+
456
+
457
+
458
+
459
+ // 受信が成功したか(async_read用で,引数は固定)
460
+
461
+ void OnReceive(const boost::system::error_code& error, size_t bytes_transferred)
462
+
463
+ {
464
+
465
+ if (error && error != asio::error::eof)
466
+
467
+ cout << "receive failed: " << error.message() << endl;
468
+
469
+ else {
470
+
471
+ // 受信したデータをchar*に変換
472
+
473
+ const char* data = asio::buffer_cast<const char*>(receive_buff_.data());
474
+
475
+ lastData = const_cast<char*>(data);
476
+
477
+ cout << lastData << endl;
478
+
479
+
480
+
481
+ receive_buff_.consume(receive_buff_.size());
482
+
483
+
484
+
485
+ //-----編集箇所--------------------------
486
+
487
+ if (lastData[0] != 'e') {
488
+
489
+ cout << "endしないよ:" << lastData << endl;
490
+
491
+ ReceiveTCP();
492
+
493
+ }
494
+
495
+ else
496
+
497
+ cout << "endするよ" << endl;
498
+
499
+ //-----編集箇所--------------------------
500
+
501
+ }
502
+
503
+ }
504
+
505
+ ```
506
+
409
507
  ###**送信ソース**
410
508
 
411
509
 
@@ -820,104 +918,6 @@
820
918
 
821
919
  ```
822
920
 
823
- ###試したこと
824
-
825
- 参考URLのようにReceiveTCP()をOnConnect()内で呼び出すと問題なく動作するのですが,今後連続でデータ待機を行う場合に毎回Connectを行う必要が出てくるので可能であればOnConnectからReceiveTCPを呼び出す方法は避けたいと考えています.
826
-
827
-
828
-
829
- ###補足情報(言語/FW/ツール等のバージョンなど)
830
-
831
- Visual Studio 2017
832
-
833
- Boost 1.65.1
834
-
835
-
836
-
837
- ###**追記**
838
-
839
- ###受信ソース(修正箇所)
840
-
841
- ```C++
842
-
843
- // 接続が完了したか(async_accept用で、引数は固定)
844
-
845
- void OnAccept(const boost::system::error_code& error)
846
-
847
- {
848
-
849
- if (error)
850
-
851
- cout << "connect failed : " + error.message() << endl;
852
-
853
- else
854
-
855
- cout << "Success connection." << endl;
856
-
857
-
858
-
859
- //-----編集箇所--------------------------
860
-
861
- ReceiveTCP();
862
-
863
- //-----編集箇所--------------------------
864
-
865
- }
866
-
867
-
868
-
869
-
870
-
871
- // 受信が成功したか(async_read用で,引数は固定)
872
-
873
- void OnReceive(const boost::system::error_code& error, size_t bytes_transferred)
874
-
875
- {
876
-
877
- if (error && error != asio::error::eof)
878
-
879
- cout << "receive failed: " << error.message() << endl;
880
-
881
- else {
882
-
883
- // 受信したデータをchar*に変換
884
-
885
- const char* data = asio::buffer_cast<const char*>(receive_buff_.data());
886
-
887
- lastData = const_cast<char*>(data);
888
-
889
- cout << lastData << endl;
890
-
891
-
892
-
893
- receive_buff_.consume(receive_buff_.size());
894
-
895
-
896
-
897
- //-----編集箇所--------------------------
898
-
899
- if (lastData[0] != 'e') {
900
-
901
- cout << "endしないよ:" << lastData << endl;
902
-
903
- ReceiveTCP();
904
-
905
- }
906
-
907
- else
908
-
909
- cout << "endするよ" << endl;
910
-
911
- //-----編集箇所--------------------------
912
-
913
- }
914
-
915
- }
916
-
917
- ```
918
-
919
-
920
-
921
921
  実行結果
922
922
 
923
923
  それぞれ1文字ずつ[a, b, c, d, e]と送信した場合

3

送信ソース追加

2017/11/07 16:40

投稿

Unity-chan
Unity-chan

スコア20

test CHANGED
File without changes
test CHANGED
@@ -1,4 +1,6 @@
1
- ###前提・実現したいこと
1
+ ###**前提・実現したいこと**
2
+
3
+
2
4
 
3
5
   非同期で送信されるデータを,連続で受け取るプログラムの構築を目指しています.
4
6
 
@@ -6,11 +8,11 @@
6
8
 
7
9
   またMain関数からはAsioのライブラリが見えないように構築したいと考えています.
8
10
 
9
- ###現状
11
+ ###**現状**
10
12
 
11
13
  BoostライブラリのAsioを用いて構築したコードを確認するために,送信したデータを表示して終了するプログラムを構築しました.(参考:https://boostjp.github.io/tips/network/tcp.html)
12
14
 
13
- ###発生している問題・エラーメッセージ
15
+ ###**発生している問題・エラーメッセージ**
14
16
 
15
17
  実行すると以下のエラーメッセージが表示されます.(IPReceiveData.cppのOnReceive関数)
16
18
 
@@ -20,7 +22,7 @@
20
22
 
21
23
  ```
22
24
 
23
-
25
+ ###**受信ソース**
24
26
 
25
27
  ###IPReceiveData.h
26
28
 
@@ -404,6 +406,420 @@
404
406
 
405
407
  ```
406
408
 
409
+ ###**送信ソース**
410
+
411
+
412
+
413
+ 参考URLのソースから,他ソースコードから送信したい文字列を指定できるように変更した.
414
+
415
+ ###IPSendData.h
416
+
417
+ ```C++
418
+
419
+ #ifndef __IPConnect_h__
420
+
421
+ #define __IPConnect_h__
422
+
423
+
424
+
425
+
426
+
427
+ enum TransportProtocol {
428
+
429
+ TP_TCP = 1,
430
+
431
+ TP_UDP = 0,
432
+
433
+ };
434
+
435
+
436
+
437
+ class IPSending {
438
+
439
+ public:
440
+
441
+ // TCPかUDPか選択(最初に選択すれば、初期化やメッセージ送信ではTCPUDP区別なく関数を使える)
442
+
443
+ IPSending(TransportProtocol isTcp);
444
+
445
+ ~IPSending();
446
+
447
+
448
+
449
+ void ipsInitialize(char* ipAddress, char *portNum);
450
+
451
+
452
+
453
+ void ipsSendMSG(char* msg);
454
+
455
+
456
+
457
+ private:
458
+
459
+ class IPSend_impl* ips_impl;
460
+
461
+ };
462
+
463
+
464
+
465
+ #endif
466
+
467
+ ```
468
+
469
+ ###IPSendData.cpp
470
+
471
+ ```C++
472
+
473
+
474
+
475
+ #define BOOST_COROUTINES_NO_DEPRECATION_WARNING // asioはcoroutine2をサポートしていないので警告を消す
476
+
477
+ #define PIMP(x) ips_impl->x
478
+
479
+
480
+
481
+ #include <iostream>
482
+
483
+ #include <memory>
484
+
485
+ #include <boost/asio.hpp>
486
+
487
+ #include <boost/bind.hpp>
488
+
489
+ #include <boost/asio/spawn.hpp>
490
+
491
+ #include "IPSendData.h"
492
+
493
+
494
+
495
+ namespace asio = boost::asio;
496
+
497
+ using asio::ip::tcp;
498
+
499
+ using asio::ip::udp;
500
+
501
+ using std::cout;
502
+
503
+ using std::endl;
504
+
505
+ using std::string;
506
+
507
+ using std::shared_ptr;
508
+
509
+
510
+
511
+
512
+
513
+
514
+
515
+ class IPSend_impl {
516
+
517
+ private:
518
+
519
+ tcp::socket socketTCP; // TCP
520
+
521
+ udp::socket socketUDP; // UDP
522
+
523
+ udp::resolver resolver; // UDP
524
+
525
+ asio::strand strand; // spawn
526
+
527
+ udp::endpoint receiver_endpoint;
528
+
529
+ string sendData; // SendTCPでしか使わないが、使用する前にスコープ外へ出て消えてしまうので外
530
+
531
+
532
+
533
+
534
+
535
+ // 接続が完了したか(async_connect用で、引数は固定)
536
+
537
+ void OnConnect(const boost::system::error_code& error)
538
+
539
+ {
540
+
541
+ if (error)
542
+
543
+ throw "connect failed : " + error.message();
544
+
545
+ else
546
+
547
+ cout << "connect correct!" << endl;
548
+
549
+ }
550
+
551
+
552
+
553
+ void OnSend(const boost::system::error_code& error, size_t bytes_transferred)
554
+
555
+ {
556
+
557
+ if (error)
558
+
559
+ throw "send failed: " + error.message();
560
+
561
+ else
562
+
563
+ cout << "send correct!" << endl;
564
+
565
+ }
566
+
567
+
568
+
569
+
570
+
571
+ public:
572
+
573
+ asio::io_service& ioService;
574
+
575
+ const bool isTCP;
576
+
577
+
578
+
579
+
580
+
581
+ // TCPとUDPを指定して初期化するコンストラクタ
582
+
583
+ IPSend_impl(asio::io_service& ioService, TransportProtocol isTcp)
584
+
585
+ : ioService (ioService),
586
+
587
+ resolver (ioService),
588
+
589
+ strand (ioService),
590
+
591
+ socketTCP (ioService),
592
+
593
+ socketUDP (ioService),
594
+
595
+ isTCP (isTcp){}
596
+
597
+
598
+
599
+ // デストラクタ
600
+
601
+ ~IPSend_impl() {
602
+
603
+ }
604
+
605
+
606
+
607
+
608
+
609
+ // TCPの接続要求を行う
610
+
611
+ void ConnectTCP(char *ipAddress, char *portNum) {
612
+
613
+ // 接続するIPとポート番号を設定する
614
+
615
+ auto address(
616
+
617
+ tcp::endpoint(
618
+
619
+ asio::ip::address::from_string(ipAddress), atoi(portNum)));
620
+
621
+
622
+
623
+ // 接続時に実行するコールバック関数を設定する
624
+
625
+ auto cbOnConnect(
626
+
627
+ boost::bind(&IPSend_impl::OnConnect, this,
628
+
629
+ asio::placeholders::error));
630
+
631
+
632
+
633
+ // 上記で宣言したアドレスとコールバック関数を登録する
634
+
635
+ socketTCP.async_connect(address, cbOnConnect);
636
+
637
+ }
638
+
639
+
640
+
641
+ // UDPの接続要求を行う
642
+
643
+ void ConnectUDP(char *ipAddress, char *portNum) {
644
+
645
+ auto query(udp::resolver::query(udp::v4(), ipAddress, portNum));
646
+
647
+ receiver_endpoint = *resolver.resolve(query);
648
+
649
+
650
+
651
+ socketUDP.open(udp::v4());
652
+
653
+ }
654
+
655
+
656
+
657
+
658
+
659
+ // TCPでメッセージを送信
660
+
661
+ void SendTCP(char *msg)
662
+
663
+ {
664
+
665
+ sendData = msg;
666
+
667
+
668
+
669
+ // 接続後に呼ばれる関数(今回は成否出力)
670
+
671
+ auto cbOnSend(
672
+
673
+ boost::bind(&IPSend_impl::OnSend, this,
674
+
675
+ asio::placeholders::error,
676
+
677
+ asio::placeholders::bytes_transferred));
678
+
679
+
680
+
681
+
682
+
683
+ // ソケット、上記で宣言した送信データとコールバック関数を登録する
684
+
685
+ asio::async_write(
686
+
687
+ socketTCP,
688
+
689
+ asio::buffer(sendData),
690
+
691
+ cbOnSend);
692
+
693
+ }
694
+
695
+
696
+
697
+
698
+
699
+ // メッセージ送信
700
+
701
+ void SendUDP(char *msg){
702
+
703
+ }
704
+
705
+ };
706
+
707
+
708
+
709
+
710
+
711
+
712
+
713
+ // IP通信の初期化を行う
714
+
715
+ IPSending::IPSending(TransportProtocol isTcp) {
716
+
717
+ auto ioService = new asio::io_service;
718
+
719
+ ips_impl = new IPSend_impl(*ioService, isTcp);
720
+
721
+ }
722
+
723
+
724
+
725
+ IPSending::~IPSending() {
726
+
727
+ delete ips_impl;
728
+
729
+ cout << "Finalize IPSending." << endl;
730
+
731
+ }
732
+
733
+
734
+
735
+
736
+
737
+ // TCP通信の初期化
738
+
739
+ void IPSending::ipsInitialize(char *ipAddress, char *portNum) {
740
+
741
+ if (ips_impl->isTCP)
742
+
743
+ PIMP(ConnectTCP(ipAddress, portNum));
744
+
745
+ else
746
+
747
+ PIMP(ConnectUDP(ipAddress, portNum));
748
+
749
+ }
750
+
751
+
752
+
753
+ void IPSending::ipsSendMSG(char *msg) {
754
+
755
+ if (PIMP(isTCP)) {
756
+
757
+ PIMP(SendTCP(msg));
758
+
759
+ PIMP(ioService.run());
760
+
761
+ }
762
+
763
+ else
764
+
765
+ PIMP(SendUDP(msg));
766
+
767
+ }
768
+
769
+ ```
770
+
771
+ ###Main.cpp
772
+
773
+ ```C++
774
+
775
+ #include <iostream>
776
+
777
+ #include "IPSendData.h"
778
+
779
+ #define __test__
780
+
781
+
782
+
783
+ int main() {
784
+
785
+ char test[30];
786
+
787
+
788
+
789
+ IPSending ipSending(TP_TCP);
790
+
791
+
792
+
793
+ ipSending.ipsInitialize("127.0.0.1", "31400");
794
+
795
+
796
+
797
+ while (true) {
798
+
799
+ std::cout << "文字を入力してください:";
800
+
801
+ scanf_s(aaa, 10);
802
+
803
+
804
+
805
+ ipSending.ipsSendMSG(aaa);
806
+
807
+
808
+
809
+ if (aaa[0] == 'e')
810
+
811
+ break;
812
+
813
+ }
814
+
815
+
816
+
817
+ return 0;
818
+
819
+ }
820
+
821
+ ```
822
+
407
823
  ###試したこと
408
824
 
409
825
  参考URLのようにReceiveTCP()をOnConnect()内で呼び出すと問題なく動作するのですが,今後連続でデータ待機を行う場合に毎回Connectを行う必要が出てくるので可能であればOnConnectからReceiveTCPを呼び出す方法は避けたいと考えています.
@@ -418,7 +834,9 @@
418
834
 
419
835
 
420
836
 
421
- ###追記
837
+ ###**追記**
838
+
839
+ ###受信ソース(修正箇所)
422
840
 
423
841
  ```C++
424
842
 

2

追記の改善

2017/11/06 09:07

投稿

Unity-chan
Unity-chan

スコア20

test CHANGED
File without changes
test CHANGED
@@ -497,3 +497,11 @@
497
497
  }
498
498
 
499
499
  ```
500
+
501
+
502
+
503
+ 実行結果
504
+
505
+ それぞれ1文字ずつ[a, b, c, d, e]と送信した場合
506
+
507
+ ![イメージ説明](addcdf1c58916b195e3101ccd2141703.png)

1

プログラムの改善

2017/11/06 06:03

投稿

Unity-chan
Unity-chan

スコア20

test CHANGED
File without changes
test CHANGED
@@ -415,3 +415,85 @@
415
415
  Visual Studio 2017
416
416
 
417
417
  Boost 1.65.1
418
+
419
+
420
+
421
+ ###追記
422
+
423
+ ```C++
424
+
425
+ // 接続が完了したか(async_accept用で、引数は固定)
426
+
427
+ void OnAccept(const boost::system::error_code& error)
428
+
429
+ {
430
+
431
+ if (error)
432
+
433
+ cout << "connect failed : " + error.message() << endl;
434
+
435
+ else
436
+
437
+ cout << "Success connection." << endl;
438
+
439
+
440
+
441
+ //-----編集箇所--------------------------
442
+
443
+ ReceiveTCP();
444
+
445
+ //-----編集箇所--------------------------
446
+
447
+ }
448
+
449
+
450
+
451
+
452
+
453
+ // 受信が成功したか(async_read用で,引数は固定)
454
+
455
+ void OnReceive(const boost::system::error_code& error, size_t bytes_transferred)
456
+
457
+ {
458
+
459
+ if (error && error != asio::error::eof)
460
+
461
+ cout << "receive failed: " << error.message() << endl;
462
+
463
+ else {
464
+
465
+ // 受信したデータをchar*に変換
466
+
467
+ const char* data = asio::buffer_cast<const char*>(receive_buff_.data());
468
+
469
+ lastData = const_cast<char*>(data);
470
+
471
+ cout << lastData << endl;
472
+
473
+
474
+
475
+ receive_buff_.consume(receive_buff_.size());
476
+
477
+
478
+
479
+ //-----編集箇所--------------------------
480
+
481
+ if (lastData[0] != 'e') {
482
+
483
+ cout << "endしないよ:" << lastData << endl;
484
+
485
+ ReceiveTCP();
486
+
487
+ }
488
+
489
+ else
490
+
491
+ cout << "endするよ" << endl;
492
+
493
+ //-----編集箇所--------------------------
494
+
495
+ }
496
+
497
+ }
498
+
499
+ ```