|
>>1820 みみ > 各クライアントが順不同のタイミングで接続してきた場合、 > どのクライアントがどのソケットに接続しているのかを知るのには、 > どのような方法があるのでしょうか? http://X68000.startshop.co.jp/~68user/net/c-echo-2.html を見てください。 getpeername(sock, (struct sockaddr *)&peer_sin, &len) でソケットの接続先のアドレス (IP アドレス+ポート番号の 情報) が peer_sin に格納されます。 - IP アドレス … inet_ntoa(peer_sin.sin_addr) - ホスト名 … gethostbyaddr - ポート番号 … ntohs(peer_sin.sin_port) でそれぞれ取得できます。 そのページのサンプルの echo-server-select.c では、 accept したときに struct CLIENT_INFO という構造体に ホスト名・IP アドレス・ポート番号を格納し、その後 クライアントの情報が必要になったら struct CLIENT_INFO を 参照していますが、毎回ソケットに対して getpeername しても動作はします。 |
|
素早い解答、ありがとうございます。 確認の意味で、質問をさせて頂きます。 そうすると、サーバ側の処理としては、下記のように なるということでしょうか? ・クライアントからの接続がある。 (sd[i]がインクリメントされる。) ・接続してきたクライアントからの処理要求がある。 (ここで、クライアント側のプロセスが何なのかが判明する。) ・getpeername を行うことで、sd[i]の”i”の値を得る。 (これにより、接続元クライアントのプロセスとを リンクさせることができる。) 上記のような解釈で、誤りがありませんでしょうか? getpeername については、もう少し勉強をしてみます。 (実は、サンプルプログラムで良く理解できていなかった部分です。 クライアント情報を格納しているのは判ったのですが。 付け焼き刃のかなしさです。でも頑張ります。) 本当に、ありがとうございます。 後程、結果を報告に来ます。 |
|
>>1822 みみ > ・クライアントからの接続がある。 > (sd[i]がインクリメントされる。) > ・接続してきたクライアントからの処理要求がある。 > (ここで、クライアント側のプロセスが何なのかが判明する。) > ・getpeername を行うことで、sd[i]の”i”の値を得る。 > (これにより、接続元クライアントのプロセスとを > リンクさせることができる。) うーん、説明が難しいですね。一度わかってしまえば何てことはない のですが…。 クライアントとサーバとの接続点がソケットです。複数のソケットが あるとき、それらを識別するのはソケットディスクリプタ (3 とか 4 などの整数値) です。別のソケットには、必ず別のソケットディスク リプタが割り振られます。 http://X68000.startshop.co.jp/~68user/net/c-echo-2.html で言うと、 for ( i=0 ; i<FD_SETSIZE ; i++ ){ if ( FD_ISSET(i, &target_fds) ){ if ( i == listening_socket ){ accept して、新クライアントのソケットディスクリプタを取得 } else { ソケットディスクリプタ i からデータが送られてきた } } } という感じです。例えば i==5 のとき FD_ISSET が真ならば、 今からやりとりしたいのは「ソケットディスクリプタ 5」です。 このクライアントとの接続が切れない限り、この番号は不変です。 データを読みたいなら read(5, buf, sizeof(buf)) すればよいし、 データを送りたいなら write(5, "hoge", sizeof("hoge")-1) とします。 if ( i == listening_socket ){ accept して、新クライアントのソケットディスクリプタを取得 } else { len = read(5, buf, sizeof(buf)); write(5, buf, len); } とすれば、それで echo サーバのでき上がりです。ソケット ディスクリプタ 5 からデータを読んで、ソケットディスクリプタ 5 にデータを書いているので、echo した結果が別クライアントに 送られることはありません。 つまり、ソケットがいくつあっても「ソケットディスクリプタが 確定している=クライアントが識別できる」と言えます。 getpeername は、相手側の IP アドレスやポート番号を知りたい 場合に使いますが、根本的にはそれらの情報がなくてもどの クライアントとやりとりしているのか区別できます。 |
|
あ、また書き込んでくださったのですね。 重ね重ね、ありがとうございます。 >>1823の内容からすると、 「selectにより、各クライアントを固有のものとして認識できる為、 サーバ側でプログラム的に管理しなくても大丈夫。」 ということなのでしょうか? (うう、一所懸命にプログラム書いちゃいましたけど。) 昨日の書き込み(1822)の内容の処理を行うプログラムは、 意図した通りの動作をしていることは、確認できました。 が。 システムコールに依存した方が信頼性は高いので、 もう一度、見直すことにします。 ありがとうございました。 また、報告に伺います。 |
|
最初のご質問では >>1820 みみ > どのクライアントがどのソケットに接続しているのかを知るのには とありましたので、IP アドレスやポート番号などの情報が 得たいのかと思い getpeername を使えばよいという回答を しましたが、どうやらそうではないのですね。 TCP で、複数のクライアントが接続してきたときに、クライアントを 区別するために、サーバ側で何か処理を行う必要があるか、という 意味ならば、 >>1824 みみ > 「selectにより、各クライアントを固有のものとして認識できる為、 > サーバ側でプログラム的に管理しなくても大丈夫。」 という認識でよろしいかと思います。 |
|
せっかく指摘して頂いたのに返答遅れてすいませんでした。 >>1818 rosegarden 指摘して頂いたとおり、LINTを見ると関係ありそうなものはいかの 通りでした。 # snd: Voxware sound support code # sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum # sbxvi: SoundBlaster 16 # sbmidi: SoundBlaster 16 MIDI interface # pas: ProAudioSpectrum PCM and MIDI # gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX # gusxvi: Gravis Ultrasound 16-bit PCM (do not use) # mss: Microsoft Sound System # css: Crystal Sound System (CSS 423x PnP) # sscape: Ensoniq Soundscape MIDI interface # sscape_mss: Ensoniq Soundscape PCM (requires sscape) # opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum # uart: stand-alone 6850 UART for MIDI # mpu: Roland MPU-401 stand-alone card sbcドライバかguscドライバのいずれかを有効にすればよいとの後指摘でした が、私の使用しているドライバはYamahaのYMF740なので上記のうち 「opl」を有効にするのかなと初心者なりに考えて見たのですが。 >>1817 68user まだ、勉強不足でよくわからないのですが、コンフィグモードというもので 設定すると何らかの設定ファイルが書き変わるのでしょうか? まだ、恐くて試していません。 |