質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2111閲覧

siv3d の tcp通信実装(ド基礎)

Maitz.

総合スコア12

TCP

TCP(Transmission Control Protocol)とは、トランスポート層のプロトコルで、コネクション型のデータサービスです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/12/25 02:08

編集2022/02/23 17:53

前提・実現したいこと

>ここに質問の内容を詳しく書いてください。

「siv3d」を使ってゲームを作成しています。(v0.6.3)
https://zenn.dev/reputeless/books/siv3d-documentation

Visual Studio Community 2019 で編集しています。

多人数ボードゲームを作成するため、複数PCの通信機能を実装したいです。
サンプルにあった「1 対 1 の TCP 通信」を改造したのですが、うまくいきません。

発生している問題・エラーメッセージ

通信が繋がりません。
知識が足りないため、何が問題になり得るのかも想像すらついてません。基本設定を間違っているのかもしれません。

とりあえず、外部との通信でサンプルが動くようにしたいです。
問題点以外でも、基本的な注意事項など思いついたら教えていただけると助かります。

加えてこの問題以外に、時々以下のエラーが出て強制終了します。

dialog

1[std::runtime_error]close:ソケット以外のものに対して操作を実行しようとしました。:ソケット以外のものに対して操作を実行しようとしました。 2For more information, [Debug] -> [Windows] -> [Exception Settings] -> tick the C++ Exception checkbox under the [Break When Thrown] heading

該当のソースコード

チュートリアル 40 | TCP 通信
https://zenn.dev/reputeless/books/siv3d-documentation/viewer/tutorial-tcp
Siv3D_IPv4Address.ipp
https://github.com/Siv3D/OpenSiv3D/blob/main/Siv3D/include/Siv3D/detail/IPv4Address.ipp

cpp

1//サーバー側、サンプルそのまま 2# include <Siv3D.hpp> 3 4void Main() 5{ 6 // ポート番号 7 constexpr uint16 port = 50000; 8 bool connected = false; 9 10 TCPServer server; 11 server.startAccept(port); 12 13 Window::SetTitle(U"TCPServer: Waiting for connection..."); 14 15 Point clientPlayerPos{ 0, 0 }; 16 17 while (System::Update()) 18 { 19 const Point serverPlayerPos = Cursor::Pos(); 20 21 if (server.hasSession()) 22 { 23 if (not connected) // クライアントが接続 24 { 25 connected = true; 26 27 Window::SetTitle(U"TCPServer: Connection established!"); 28 } 29 30 // 送信 31 server.send(serverPlayerPos); 32 33 // 受信 34 while (server.read(clientPlayerPos)); 35 } 36 37 // クライアントが切断 38 if (connected && (not server.hasSession())) 39 { 40 // 切断 41 server.disconnect(); 42 43 connected = false; 44 45 Window::SetTitle(U"TCPServer: Waiting for connection..."); 46 47 // 新たな接続を受け付け開始 48 server.startAccept(port); 49 } 50 51 Circle{ serverPlayerPos, 30 }.draw(Palette::Skyblue); 52 53 Circle{ clientPlayerPos, 10 }.draw(Palette::Orange); 54 } 55}

cpp

1//クライアント側 2# include <Siv3D.hpp> 3# include <winsock.h> 4 5void Main() 6{ 7 // 接続先の IPv4 アドレス(今回は自身の PC なので Localhost) 8 IPv4Address ip = IPv4Address::Localhost(); 9 10 // ポート番号 11 constexpr uint16 port = 50000; 12 13 bool connected = false; 14 15 TCPClient client; 16 17 // 接続を試行 18 client.connect(ip, port); 19 20 Window::SetTitle(U"TCPClient: Waiting for connection..."); 21 22 //IP入力用テキストボックス 23 TextEditState te0; 24 TextEditState te1; 25 te1.text = U"Siv3D"; // デフォルトの文字列 26 TextEditState te2; 27 TextEditState te3; 28 29 30 Point serverPlayerPos{ 0, 0 }; 31 32 while (System::Update()) 33 { 34 const Point clientPlayerPos = Cursor::Pos(); 35 36 //IP入力用テキストボックス 37 SimpleGUI::TextBox(te0, Vec2{ 100, 140 }); 38 SimpleGUI::TextBox(te1, Vec2{ 100, 200 }); 39 SimpleGUI::TextBox(te2, Vec2{ 100, 260 }); 40 SimpleGUI::TextBox(te3, Vec2{ 100, 320 }); 41 42 if (SimpleGUI::Button(U"invite", Vec2{ 420, 200 })) 43 { 44 //ボタンが押された時、一旦通信切断 45 client.disconnect(); 46 47 connected = false; 48 49 Window::SetTitle(U"TCPClient: Waiting for connection..."); 50 51 //テキストボックスから文字列取得、数値型で仮保持。 52 //const String s = te1.text; 53 //std::string str = s.narrow(); 54 //ip = inet_addr(str.c_str()); 55 int32 num_a = ParseOr<int32>(te0.text, 10); 56 int32 num_b = ParseOr<int32>(te1.text, 10); 57 int32 num_c = ParseOr<int32>(te2.text, 10); 58 int32 num_d = ParseOr<int32>(te3.text, 10); 59 60 //IP変数に代入して、接続を再試行 61 ip = IPv4Address::IPv4Address(num_a, num_b, num_c, num_d); 62 // 接続を再試行 63 client.connect(ip, port); 64 } 65 66 if (SimpleGUI::Button(U"Clear", Vec2{ 420, 300 })) 67 { 68 client.disconnect(); 69 70 connected = false; 71 72 Window::SetTitle(U"TCPClient: Waiting for connection..."); 73 74 ip = IPv4Address::Localhost(); 75 // 接続を再試行 76 client.connect(ip, port); 77 } 78 79 if (client.isConnected()) 80 { 81 if (not connected) // 接続された 82 { 83 connected = true; 84 85 Window::SetTitle(U"TCPClient: Connection established!"); 86 } 87 88 // 送信 89 client.send(clientPlayerPos); 90 91 // 受信 92 while (client.read(serverPlayerPos)); 93 } 94 95 if (client.hasError()) // 切断/接続エラー 96 { 97 client.disconnect(); 98 99 connected = false; 100 101 Window::SetTitle(U"TCPClient: Waiting for connection..."); 102 103 // 接続を再試行 104 client.connect(ip, port); 105 } 106 107 Circle{ clientPlayerPos, 30 }.draw(Palette::Skyblue); 108 109 Circle{ serverPlayerPos, 30 }.draw(Palette::Orange); 110 } 111}

試したこと

>ここに問題に対して試したことを記載してください。

サンプルプログラムは同一pc上で通信する仕様で、想定通り動作しました。
次に改造したプログラムを同一pc上でテストしました。「IPv4Address::Localhost();の代入」「手動の"127.0.0.1"代入」「関係ないアドレスでのエラーチェック」いずれも想定通り動作しました。

その後上記のプログラムを2つのpcにて実行。
サーバー側のpcで「ipconfig」を実行し、イーサネットのIPv4アドレスを特定。
クライアント側で入力したところ、接続できず。

補足情報(FW/ツールのバージョンなど)

>ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2021/12/25 02:37 編集

示されたクライアント側コードは同一PC上で動作するものだから繋がらないのはアタリマエかと。 > クライアント側で入力したところ、接続できず。 クライアント側コードで、IP入力しているのはどこですか?
Maitz.

2021/12/25 02:52

どうすれば同一PC以外でも動作するのか、質問したいと思ってます。 >IP入力している部分 /*** int32 num_d = ParseOr<int32>(te3.text, 10); ip = IPv4Address::IPv4Address(num_a, num_b, num_c, num_d); ***/ この部分で、エディットボックスの文字列を数値型に変換、変数"ip"に代入しています。 この上下に「client.disconnect();」「client.connect(ip, port);」があります。
dodox86

2021/12/25 02:52

> サンプルにあった「1 対 1 の TCP 通信」を改造したのですが、うまくいきません。 改造をする前は動いていたのでしょうか。まず、それを確認してからの改造作業だと思います。
Maitz.

2021/12/25 02:58

記載不足でした。 サンプルは同一pc上で通信する仕様で、想定通り動作しました。 次に改造したプログラムを同一pc上でテストしました。「IPv4Address::Localhost();の代入」「手動の"127.0.0.1"代入」「関係ないアドレスでのエラーチェック」いずれも想定通り動作しました。
episteme

2021/12/25 04:21 編集

で、サーバーはIP-reachableになってるのかしら。 クライアントPCから ping 打って反応してくれるんですよね? 当該portは開いてるんですよね?
dodox86

2021/12/25 05:12

> サンプルは同一pc上で通信する仕様で、想定通り動作しました。 であればサンプルプログラムの段階(つまり、1対1)でサーバー、クライアントそれぞれ別のPCで(つまりローカルではなくリモート)で接続、通信できることを確認されてから1対Nへの改造をすべきだと思います。epistemeさんが指摘されているよう、ネットワークの問題をクリアしてから。
Maitz.

2021/12/26 03:10

「ping (ip)」でコマンドあってますか? 要求がタイムアウトしました。と出たので、 クライアント > サーバー が繋がらないっぽいです。 ソースコードというよりネットワークの問題な気がしてきました。 portが開いてるかどうかはどうやって判断するのかわかりません。 現段階の改造では、1対1通信のままの仕様です。 サンプルプログラムはローカル(同pc)での通信にしか対応してないので、まずはリモート(他pc)通信を試行してます。
guest

回答2

0

自己解決

何故か発生しなくなりました。マシン同士の相性でしょうか?
解決としては良くないですが、質問を閉めます。回答してくださった方々、ありがとうございました。

投稿2022/02/23 08:53

Maitz.

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まずは、同じLAN内にあるPCどおしでやってみましょう
あいてのPCのIPにPINGを飛ばして、つながってるのを確認したうえで、やってみたらどうなるでしょう。

投稿2021/12/25 05:40

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Maitz.

2021/12/26 03:11

「ping (ip)」でコマンドあってますか? 要求がタイムアウトしました。と出たので、 クライアント > サーバー が繋がらないっぽいです。
y_waiwai

2021/12/26 03:25

大前提として、同じlan同士で繋がってないと無理ですが、それは大丈夫でしょうか
Maitz.

2021/12/26 04:12

同一のルーターに接続されている という意味なら、大丈夫です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問