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

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

ただいまの
回答率

89.13%

ソケット通信のデータ型?

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 4,880

sin_250

score 106

きわめて初歩的な質問だと思うのですが、よろしくお願い致します。

【やりたいこと】
とある目的のため、2台のPCをTCP通信して協調的に動かしたいです。
ざっくり言えば、2台のPC上でそれぞれアプリケーションが動いており、
片方のアプリが停止したらそれをもう片方に伝えてそちら側のアプリが動き出す、みたいなことです。

【言語】
C++です。(が他言語でも本件は同じようなものだと思うので、他言語での回答でも有難いです)

【疑問】
・2台のPC間でTCPのソケット通信をして、メッセージのやり取りをしようと考えています。
・ソケット通信のサンプルプログラムを見ると、
(C言語なら)write(sock, "HELLO", 5), read(sock, buf, sizeof(buf))のように
文字列のやり取りをしているサンプルが多いです。(というかそればかり)。

ソケット通信でメッセージをやり取りする時のデータはどういう形式が王道なのでしょうか?
例えば、上記の例で、片方のPCが相方のPCに「自分のアプリが止まったらそっちで動作開始してね」と伝えたいとき、
片方で

write(sock, "I_STOPPED", 9);


として、もう片側で

read(sock, buf, sizeof(buf));
string result(buf);
if (result == "I_STOPPED") {
  I_start();
}


などとするのでしょうか?
(・・・なんか違うんじゃないか、文字列で伝えるより洗練されたやり方があるのではないかと思っています。)

浅学で恐縮です。
アドバイスのほどよろしくお願い致します。

以上

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+4

こんにちは。

ソケット通信でメッセージをやり取りする時のデータはどういう形式が王道なのでしょうか?

IP通信するコンピュータ同士は、同じCPUでない可能性を無視できません。
なのでバイナリ形式では互換性が無いこともかなり多いです。特にエンディアンですね。
この問題が発生しにくいので文字列形式が多いのだと思います。バイナリで処理系フリーでやりとりできる仕組みを実装した後、文字列でやり取りしたら、その楽さに感動するレベルです。

単に「停止した」と言うタイミング情報しか送らないのであれば送るデータはなんでも良いと思います。
何か変なパケットが紛れ込んできて誤動作しないよう多少のプロテクトをかける意味で"I_STOPPED"であることを確認するのはありと思います。(プロトコルを知っている悪意のある人がいると簡単にいたずら?されるかも。)

ところで、"I_STOPPED"の送信時、最後のNULL文字を送信していないようです。事前のbufクリアをお忘れなく。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/27 23:41

    少し調べなおしてみましたが、おっしゃるようにバイナリデータの送受信は環境によってアラインメント?やエンディアン、int型等のサイズ違いなどの問題があるようですね。
    つまりは、テキストベースのやり取りは結構筋よしということなのでしょうか?
    \0についてはご指摘の通りです。ありがとうございます。

    ちなみに、Chironian様がTheolizerの開発者様であることを承知の上でお聞きするのですが、
    通信用のメッセージクラスあるいは構造体をシリアライズして送受信する場合でも
    上記のようなエンディアンなどの問題は生じるのでしょうか?

    質問ばかりで恐縮です。もしご教示頂けましたら幸いです。

    キャンセル

  • 2017/06/28 00:11

    いえいえ、Theolizerを知っていて頂けるだけでもたいへん嬉しいです。

    > つまりは、テキストベースのやり取りは結構筋よしということなのでしょうか?

    htmlが正にそのケースですね。xmlならデータのやり取りもできます。最近のデータのやり取りフォーマットはJsonが流行っているよう思います。
    これらは全てテキスト・ベースです。

    > 通信用のメッセージクラスあるいは構造体をシリアライズして送受信する場合でも上記のようなエンディアンなどの問題は生じるのでしょうか?

    Theolizerはバイナリー形式でもエンディアンの問題は発生しないよう設計しています。ただエンディアンの異なるCPUに移植できていないのでテストは出来ていません。orz
    異言語間をサポートするProtocol BuffersやMessagePackはフォーマットを確認したことありますがエンディアンを吸収しています。
    C++用のシリアライザであるboost::serializationやcerealについては把握していませんが、恐らくエンディアン問題は吸収しているのではないかと思います。

    ところで、Theolizerとboost::Asioを使ってTCP/IPでポインタを含む複雑なデータ構造をやり取りするサンプルとその解説を↓に置いてます。
    https://theolizer.com/theolizer/tcp_ip_sample/

    同様なことをboost::serializationやcerealでも可能な筈です。シリアライザって便利ですよ。

    キャンセル

  • 2017/06/30 21:48

    なるほど、バイナリ形式でもこういう便利なのを遣えばある程度細かい部分は隠ぺいしてもらえるのですね。
    データが小さいならJSONでも十分そうですね。
    改めて必要パフォーマンスを考えて決めてみます。ご回答ありがとうございました。

    キャンセル

+2

ソケット通信でメッセージをやり取りする時のデータはどういう形式が王道なのでしょうか?

ソケット通信(TCP/UDP)はプロトコルスタックの下位レイヤしか提供しませんから、"メッセージ"のやり取りには何らかの上位レイヤ・プロトコル(メッセージフォーマット)を選択する必要があります。

コレを選べば間違いなしと言える程の王道はありませんが、下記プロトコル(ライブラリ)が一般に広く使われているようです:

テキストベースのプロトコルは通信オーバーヘッド(データ量や送受信処理の負荷)が大きめですが、他言語とのやり取りや通信内容の確認を容易に行えます。バイナリベースのプロトコルは通信オーバーヘッドを抑えられますが、他言語とのやり取り(相手方がスクリプト系言語など)や通信内容の確認が面倒なことが多いです。


例えば、上記の例で、片方のPCが相方のPCに「自分のアプリが止まったらそっちで動作開始してね」と伝えたい

要件次第ですが、本当に単純な通信しか行わないのであれば、独自のメッセージフォーマット/通信プロトコルを定義してしまうというやり方もあります。ただし、将来的に拡張したくなったりすることを考えると、汎用性のあるプロトコルを採用してしまったほうが無難でしょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/28 21:16

    ご回答ありがとうございます。なるほど、JSONなどは普段使っていますが、テキストベースで構造も入れ込めてライブラリもあるし、便利ですね。
    MessagePackなども存じませんでした。ご教示頂きありがとうございました。

    キャンセル

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

  • ただいまの回答率 89.13%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る