- ベストアンサー
TCP/IPプログラミング
2台のコンピュータA,Bがあるとします。1つのポートを使って、ある時はAから送信します。またある時はBから送信します。場合によれば、お互い同時に送信を開始するかもしれません。 こういう条件の時、A,Bに送信、受信のプログラムをそれぞれに置いて、特に問題ないでしょうか? 要は1つのポートを使って4本のプログラムが動作することになります。 問題が起こるとすれば、どういうことが考えられるでしょうか? 宜しくお願いします。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
>「データ送信前に、データを受信し、その後、送信する」という意味はselectで待ってFD_ISSETで受信データの有無を調べるという風に解釈しました。 はい、それでOKです。 >その場合、前者の方法で実現するとなるとselectから何らかの方法で抜けないと2)のヘルスチェックを送る処理に移行できないような気がします。selsectの第3パラメータのwritefdsを使用するのでしょうか? selectでタイムアウト時間を指定します。 selectの戻り値>0の時、受信有り selectの戻り値<0の時、selectのエラー selectの戻り値=0の時、受信なし となります。 >「この間ヘルスチェックは送れなくなるが、送れなくてもかまわないはず。」になるのでしょうか? はい、その通りです。ヘルスチェックは、双方の生存確認のためですから、データ送信中は、このこと自体が生存確認を行っていると考えて良いはずです。 >最後に後者の作り方について、URL、サンプルプログラムなど御座いましたらご教示願えないでしょうか? 役にたつかどうか不明ですが、参考URLをあげときます。(私もこのサイトを詳細に見たわけではありませんので、その点あらかじめ了承下さい。)
その他の回答 (5)
- tatsu99
- ベストアンサー率52% (391/751)
1.一定間隔でAからBにヘルスチェックが送られ、Bからその応答を返す。 2.BでAからの取得要求が、発生したときは、BからAに取得要求を送る。 そのあとのことが、記述されていませんが、それを受けて、Aは取得要求に対応したデータ(たぶん大量のデータ)をなくなるまで送る。・・ということで良いのでしょうか。 上記の前提で、良いとすれば、以下のよう手順になると思います。 ------------------------------------------------ 1つのセッションで実現する方法です。 どちらをサーバとしてもかまいませんが、今回はAをサーバとします。Aがポート5000でリッスンし、接続が完了後の処理です。 1.Aは以下の処理を繰り返します。 1)Bからの電文の受信がないかチェックする。 2)無ければ、ヘルスチェックをBへ送る。(但し一定間隔の時間が到来時のみ送る) 3)Bからの受信があれば、以下の処理を行う。 (1)ヘルスチェックの応答なら受け捨て。 (2)データ取得要求なら、それに応じたデータをBへデータが無くなるまで送る。(この間ヘルスチェックは送れなくなるが、送れなくてもかまわないはず。) 2.Bは以下の処理を繰り返す。 1)Aからの電文を受ける。 2)ヘルスチェックならその応答を返す。 3)Aからのデータ電文であれば、無くなるまで受け続ける。 4)データ取得要求が発生したかチェックする。 発生していれば、Aへデータ取得要求を送る。 ----------------------------------------------- >データ送信前に、データを受信し、その後、送信するようなことはやりたくないのです。いや、やりたくないというより、そういうスペックが設定されていないからです。 この意味が不明ですが、「スペックが設定されていない」とは、どういうことですか。「データ送信前に、データを受信し、その後、送信する」のは内部の処理手順の話ですので、スペックが設定されていなくても問題ないと思いますが、いかがでしょうか。 1プロセスで強引に2セッションを作成する場合は、 以下のようになると思います。 ----------------------------------------- A側の仕様 1.Aがサーバと5000でBからの接続をまつ。 2.Bから接続された場合、以下の処理に遷移。 3.一定間隔でBへヘルスチェックを送り、その応答を受けとる処理を行う。 4.Bにクライアントとして接続し、接続完了後は、 Bからのデータ要求を受信する。受信後は、Bへデータを送る。 上記で3と4は見かけ上、並行して動作する必要があります。シングルスレッドの場合は、上記3,4を交互に呼び指す仕組みが必要です。マルチスレッドの場合は、3と4は別スレッドにします。(又はforkして別プロセスという手もあります) --------------------------------------------- B側の仕様 1.ヘルスチェック処理 1)クライアントとして、Aに接続する。 2)Aからの電文を受信後、応答を返す。 2.データ取得処理 1)サーバーとして、ポート5000でリッスンする。 2)Aからの接続を確認後、データ取得要求の発生をまつ。 3)データ取得要求の発生時、Aへデータ取得要求を送信する。 4)Aからのデータを受信する。 上記で1と2は、見かけ上並行して、動作する必要があります。マルチスレッド、又はforkする場合は、A側の処理 と考え方は同じです。 ----------------------------------- 私、個人としては、最初の方法を勧めます。(それがもっとも簡単だと思われますので)
お礼
お礼 遅くなり申し訳ありませんでした。「データ送信前に、データを受信し、その後、送信する」という意味はselectで待ってFD_ISSETで受信データの有無を調べるという風に解釈しました。 その場合、前者の方法で実現するとなるとselectから何らかの方法で抜けないと2)のヘルスチェックを送る処理に移行できないような気がします。selsectの第3パラメータのwritefdsを使用するのでしょうか? もうひとつ不明点があるのですが、 前者の方法を採用した場合のみ 「この間ヘルスチェックは送れなくなるが、送れなくてもかまわないはず。」になるのでしょうか? 後者のやり方は、並行処理を行うので待たされないのですよね。 最後に後者の作り方について、URL、サンプルプログラムなど御座いましたらご教示願えないでしょうか? 宜しくお願い致します。
- tatsu99
- ベストアンサー率52% (391/751)
>例えばマシンAのプロセスからBに対して送信した場合はBのプロセスはサーバの役割をする。その逆も対応する。 >つまり、1つのプロセスである時はサーバの役割をし、またある時はクライアントの役割をするといった感じです。 このようなプログラムがつくれるかということですが、結論から言えば、作れます。 しかしながら、そのようなプログラムにする必要性が判りません。 あなたが、1つのプロセスで、クライアントかつサーバーとして動作するプログラムを望んでいるのは、A->BかつB->Aのデータ送信を行いたいからではないでしょうか。もし、そうだとすると、 一方(A)がクライアントとして起動され、他方(B)がサーバーとして起動された時、データの送信は、A->Bの方向だけでなく、B->Aの方向にも、送信が可能です。もちろん1つのセッションが確立された状態でです。 従って、一方はクライアント、他方はサーバーとして動作するプログラムがあれば、それで十分であると考えます。(通常はそのような作り込みをします) この場合は、データ送信前に、データを受信し、その後、送信することが必要になります。但し、データの受信をどの程度行うかは、両者の取り決めが必要になるかと思いますが。又この場合は、ノンブロッキングモードで送受信を行うことが前提となります。 作りたいプログラムの要件としては、マシンA,B間でA->B、かつB->Aのデータ送信が行えること、ということは、判るのですが、それだけでは、どのように実現するかについての回答ができません。もっと具体的にやりたいことを提示していただければ、具体的な、実現方法の回答が得やすくなるかと思います。 不明な点は、 1.1回のデータの送信が完了したら、1)その都度、セッションを切断するのか、2)それとも、接続した状態にしておきたいのか、3)それとも、プロセスを落としたいのでしょうか。 2.送るべきデータは、どのようなデータなのでしょうか。送るべきデータの発生するタイミングは、どのような時でしょうか。
お礼
ご回答ありがとうございます。まず必要性なのですが、以下を満足するものを作りたいからです。 (1)使用できるポートは1個(この例では5000)である。 (2)AからBに対してヘルス信号を送り、Bはそれを受けて返答をAに返す。 (3)Bである事象が発生した場合はAに存在するデータを取得するために通信したい。 (4)データ送信前に、データを受信し、その後、送信するようなことはやりたくないのです。いや、やりたくないというより、そういうスペックが設定されていないからです。 (5)1つのプロセスでサーバ、クライアント処理が実現できるならスキルアップのために知りたいという気持ちです。 不明点に対する答えは以下の通りです。 (1)レスポンスを考慮してマシン立上げ時に接続したらそのセッションは切断しない。 (2)上にも書きましたが、AからBへ送るデータはヘルスチェック用の極小さなパケットです。BからAに送るデータは要求内容にもよりますが、1パケットでは送れないデータも存在します。 要求のタイミングはAからBは一定周期(例えば5分周期)で、BからAはBのマシンでデータ取得要求が発生したタイミングです。 以上 宜しくお願い致します。
- terra5
- ベストアンサー率34% (574/1662)
#1の補足にあるような処理なら動作自体は問題ありませんが、1つのポートを使うという考え方が実際のTCP通信と異なります。 通信はポートとポートの間で行なわれますから、単一のポートでは通信は行えません。 固定のポート番号は一つだけ使ってますが、確か実際に通信に使用しているポート番号は異なります。 プログラムを見ていないから正確には分かりませんが、補足説明の状態だと、多分実際は6つのポートを使っている(使っていた)ことになっていると思います。 1) マシンAの5000(サーバーが接続リクエストを受けるポート) 2) マシンBの5000(サーバーが接続リクエストを受けるポート) 3) マシンA上でサーバーがBとの通信で使うポート 4) マシンA上でクライアントがBとの通信で使うポート 5) マシンB上でサーバーがAとの通信で使うポート 6) マシンB上でクライアントがAとの通信で使うポート 3~4で使用されるポート番号は自動的に割り振られます。 リクエストを受けるポートと実際の通信を行うポートが同じなら、4ポート使ったことになると思いますが。
お礼
ご回答ありがとうございます。No.2の方がおっしゃっているように、サーバはポート5000でlistenし、クライアントは5000のポートに対してconnectするようなプログラムです。 以上のことから必ずポート5000で通信と思っていたのですが・・・・。 もしNo.3の方がおっしゃるように自動的にポートが割り振られるとすれば、必ず指定のポートで通信するプログラムはどのように作るのでしょうか? ご教示お願い致します。
- tatsu99
- ベストアンサー率52% (391/751)
>(1)マシンAとBでそれぞれ受信(サーバ)プロセスを動作させ受信可能状態にしておく。 >(2)マシンAの送信(クライアント)プロセスからマシンBへポート5000で接続して・・・ この意味は、サーバ側でポート5000でリッスンし、クライアント側で、サーバ側のポート5000に対して接続すると解釈してよろしいでしょうか。 そうであれば、この方法で問題ありません。 この方法は、ftpのサーバーに対してftpのクライアントが接続するケースと同じです。 ftpサーバは21のポートでリッスンし、ftpクライアントは21のポートに対して接続します。これをお互いのマシンで、同時にサーバーとクライアントを起動しても、問題なく動作します。(21のポートは制御用に使用しますが意味は同じです)
お礼
ご回答ありがとうございます。おっしゃるようにftpの原理と同様ですね。そうであれば問題が生じることはありませんね。納得しました。 私の考えでは、同一ポートを使ってお互いに送受信を行うと、データが入り混じるのではないかと思っておりました。 例えばマシンAに文字Aが入ってくるのではと考えていました。 もしよろしかったら、もうひとつ教えていただきたいのですが・・・。 この例では、マシンA、Bにサーバ、クライアントをそれぞれ置いています。 同様の条件下において、マシンA、Bにそれぞれ1個のプロセスで対応できるようなプログラムは組めるのでしょうか? 例えばマシンAのプロセスからBに対して送信した場合はBのプロセスはサーバの役割をする。その逆も対応する。 つまり、1つのプロセスである時はサーバの役割をし、またある時はクライアントの役割をするといった感じです。具体的なプログラムがあれば嬉しいのですが。 宜しくお願いいたします。
- anmochi
- ベストアンサー率65% (1332/2045)
> A,Bに送信、受信のプログラムをそれぞれに置いて、 ここの意味がちょっとわからない。4つのEXEがあると思って良いのかな? その場合は残念ながら実行する事はできない。 TCP/IPのプログラムは、片方がサーバになり、もう一方がクライアントになる。具体的には、サーバがソケットを作りxxx.xxx.xxx.xxx:80で待ち受け、クライアントはxxx.xxx.xxx.yyy:zzzz(ポート番号はOSが決める)でソケットを作り、xxx.xxx.xxx.yyy:80に接続する。すると2点間に電話がつながった状態になる。 ここで、サーバもクライアントもソケットに対して読み書きする事で相互にデータをやり取りできる。つまり、サーバ、クライアントともに送信と受信を1つのポートで行えるわけだ。 典型的な例では、HTTPというプロトコルがあるが、基本的には 1.サーバは80番で待ち受け 2.クライアントは適当なポートからサーバの80番に接続 3.クライアントからHTTPリクエストを送信、サーバは受信 4.サーバからHTTPレスポンスを送信、クライアントは受信 5.クライアントからTCPを切断 という流れでページも画像も音楽もPDFも動作しており、記述の通り1つのTCP/IP通信でお互いが送信も受信も行っている。なので、2本のプログラムを作る事になる。 お互いが同時に送信を開始しても、受信側でデータを受け取らないはずがない(バグ以外)ので、ソケットの基本的な使い方を学べばどうプログラムを組めばよいかは大丈夫だろう。
補足
早速のご返事ありがとうございます。おっしゃるとおり合計4つの実行モジュールがあるということです。OSはUNIX系です。 昨日簡単なテストプログラムを作って実行してみました。 (1)マシンAとBでそれぞれ受信(サーバ)プロセスを動作させ受信可能状態にしておく。 (2)マシンAの送信(クライアント)プロセスからマシンBへポート5000で接続して文字Aを100万個送信する。 (3)(2)とほぼ同時にマシンBからマシンAに対してポート5000で同数の文字Bを送信する。 (4)マシンAとBで受信した内容を確認した結果、マシンAはBという文字を100万個、マシンBはAという文字を100万個受信していました。 以上の結果から、この方法が可能だと思いました。 でもおっしゃるように、このような考え方(同一ポートを使ってお互いに送信から始まる例)はネットで検索しても見当たりません。 同一ポートを使ってマシンAから送信が始まる場合と、マシンBから送信が始まる場合のプログラム設計ってどうやるのでしょうか?
お礼
ありがとうございました。 早速試してみます。 今後とも宜しくお願いします。