none
Winsockにおけるconnect関数の動作について RRS feed

  • 質問

  • 御世話になっております。

    現在、VC++でTCPによりサーバと通信を行うPG開発を行っております。

    クライアントPGの場合、socket関数でソケットを作成後にconnect関数でサーバとの接続を確立しますが、その時OSから動的にクライアントのローカルポートを割り当てられるという認識でおります。

    ここで質問なのですが、例えばサーバがダウンしているような場合connect関数がエラーとなりますが、その時にもポートは割り当てられるのでしょうか。

    割り当てられる場合、明示的にclosesocket関数でソケットをクローズしてやらないと割り当てられたポートが開放されないのでしょうか。

    基本的なことを聞いてしまっているかも知れませんが、宜しくお願いいたします。

    ■開発環境

    OS:Windows Server 2012

    開発言語:Visual C++ 2013

    2016年9月13日 4:12

すべての返信

  • connect()失敗に対してはclosesocket()は必要ありませんが、connect()の成否に関わらずsocket()で得られたsocketはclosesocket()する必要があります。
    2016年9月13日 4:34
  • 御回答有難うございます。

    connect関数でエラーになった場合でもsocketをクローズしなければならないのですね。了解致しました。

    connect関数でエラーになった場合、やはりclosesocketしないと動的ポートが開放されないままとなり、そのうちポートが枯渇してしまう、という認識でよいのでしょうか?

    2016年9月13日 5:05
  • bindしていなければ枯渇はしないと思います。
    2016年9月13日 8:22
  • connect発行した段階で、ローカルポートは割り付くので、枯渇してしまうとおもいます。

    jzkey

    2016年9月13日 10:19
  • 佐祐理様、jzkey様、御回答有難うございます。

    当方で開発しているPGはサーバ接続を確立するまで1秒間隔で接続しに行く仕組みsocketになっているのですが、サーバを起動しない状態で放置しておくと暫く立つと通信が行えない状態となりました。

    (TCP/IPのテストツールでポートをbindしようとするとエラーとなる)

    このような現象から、connect関数でポートが割り当てられると、connectで失敗しても(closesocket関数を呼ばないと)ポートが開放されず、ポートが枯渇してしまうのかな?と推測しておりました。

    2016年9月13日 11:34
  • ちょっとjzkeyさんと質問者さんの想定されている状況がわからないのです。

    私としてはsocket()したらclosesocket()が必要と説明しています。jzkeyさんとしては「枯渇してしまう」についてどのような対処方法をお考えなのでしょうか?

    また質問者さんにも確認です。既にclosesocket()すべきと説明しましたが、「通信が行えない状態」はclosesocket()した上で発生したのでしょうか? それとも1つのsocketを使いまわした際に発生したのでしょうか? また問題の状況でnetstatの出力結果は確認されましたでしょうか?

    Windowsに限らずTCP/IPプログラミングにおいて一般的にはSO_REUSEADDRを設定しますがその点はどうでしょうか?

    2016年9月13日 13:30
  • socketにペアとして、closesocketが必要、という話には異論はないです。

    その後に派生した雑談的な質問「connectが失敗した際、【closesocket関数を呼ばないと】ポートが開放されず、ポートが枯渇してしまうのか?」に対して、「bindしていなければ枯渇しない」という回答は妥当でない、と感じたので「枯渇する」と返信いたしました。


    jzkey

    2016年9月13日 14:16
  • 回答が遅れてすみません。

    socketを作成したら必ずclosesocketしなければならない件は了解致しました。

    前回の発言はconnect関数がエラーだった場合にclosesocketをしていなかった場合の動作について述べたものでした。言葉足らずですみません。

    この件につきまして、通信が出来なくなった原因を客先に説明しなければならなかった為、クライアントアプリでconnect関数失敗時にもclosesocketしないと動的に割り当てられたポートが開放されないという推測が正しいのかどうかの確証が欲しかったもので質問させて頂きました。

    SO_REUSEADDRオプションについては不勉強ゆえ知りませんでしたので、設定しておりません。

    2016年9月14日 10:37
  • netstatは確認されましたでしょうか?

    openしたリソースはそれぞれ適切な方法でcloseするのは当然であり、エラーが発生したらcloseしなくてもよいなどということはありません。

    今回であればsocket()関数で得たSOCKETはclosesocket()で閉じなければSOCKETが枯渇します。しかし、SOCKETよりも「TCPポート」の方が少なかったためにポートが枯渇したのかもしれません。これに関しては不適切なコーディングなので何が発生したのか断言することはできません。

    念のため手元のWindows 10環境で不適切にclosesocket()を実行せず、connect()をあえて成功させずに放置したところ、ある程度動作しました。先に指摘したnetstatコマンドを使用すると「TCPポート」の使用状況を確認することができますが、毎秒socket()&connect()を実行しても使用中のTCPポートは20個程度に収まっており、順次解放されているようにも見えました。
    質問者さんの環境はWindows Server 2012とのことですので、この辺りの挙動はまた異なるのかもしれません。

    もちろんclosesocket()をした場合は毎秒socket()&connect()を実行しても使用するTCPポートは1個でした。

    2016年9月14日 21:45
  • フォーラム オペレーターの星 睦美です。
    aaaaaaaaabbbbbbbbbbbcccccccccc さん、投稿ありがとうございます。
    今回はjzkey さん、佐祐理 さんから返信があります。フォーラム ユーザー からの回答が参考になりましたら投稿者から[回答としてマーク] をお願いいたします。


    フォーラム オペレーター 星 睦美 - MSDN Community Support

    2016年9月16日 6:51