約1年半前に、OpenVOSリリース17.1でのacceptの動作方法の変更点についてのブログを書きました。この変更は、アプリケーションコードがPOSIXベースの場合にのみ有効であるということです。要約すると、17.1以前のSTCPは、サーバアプリケーションコードが acceptルーチンを呼び出した場合にのみ、クライアント接続要求に応答していました。コードが accept を呼び出さなかった場合、クライアントの接続要求はキューに入りますが、応答されることはありませんでした。アプリケーションが accept を呼び出すと、STCP は接続応答を送信します。クライアントがまだ待機している場合は、その時点で接続が完了します。クライアントがすでにあきらめていた場合は、接続応答にリセットで応答し、STCPは接続を破棄し、acceptはハング(ブロッキングモードを想定)して別の接続を待つことになります。
図1はこのシナリオを示しています。左端のテキスト行はサーバアプリケーションからのステータスメッセージであり、字下げされたpacket_monitor行(少し修正されています)はクライアントの活動の結果です。アプリケーション(acceptTestnoPosix)が起動され、ポート12345をリッスンし、一旦リッスンすると300秒間スリープ状態になります。クライアントはその後、Syn (S) フラグを設定してポート 12345 に TCP セグメントを送信し、ポート 12345 への接続を行います。これは3回トライしてからあきらめます。300 秒後にアプリケーションが起動し、accept を呼び出します。STCP スタックは、Syn および Ack (SA) フラグが設定された TCP セグメントでクライアントに応答します。リセット(R)を送信すると、クライアントは接続の記録を持たなくなるため、STCPはこの時点でブロックします。もしソケットがノンブロッキングモードであれば、ACCEPTはEAGAINエラーを返します。
acceptTestnoPosix 12345 acceptTestnoPosix 12345 の実行 300秒睡眠 11:04:45.923 R TCP 164.152.77.50 164.152.77.217 11071 12345 S 11:04:48.925 R TCP 164.152.77.50 164.152.77.217 11071 12345 S 11:04:54.937 R TCP 164.152.77.50 164.152.77.217 11071 12345 S ポート番号12345での接続を受け入れる準備ができました。 11:09:41.852 T TCP 164.152.77.217 164.152.77.50 12345 11071 SA 11:09:41.854 R TCP 164.152.77.50 164.152.77.217 11071 12345 R |
図1 - プリ17.1または非POSIXポスト17.1を受け入れる
アプリケーションがPOSIXベースの場合、状況は異なります(図2)。STCPは接続要求(S)に対して即座に応答します(SA)。その後、300秒後にアプリケーションがウェイクアップし、acceptを呼び出し、STCPは受け入れられたソケットを返します。
acceptTestwithPosix 12345 acceptTestnoPosix 12345 の実行 300秒睡眠 10:58:43.962 R TCP 164.152.77.50 164.152.77.217 11024 12345 S 10:58:43.964 T TCP 164.152.77.217 164.152.77.50 12345 11024 SA 10:58:43.964 R TCP 164.152.77.50 164.152.77.217 11024 12345 A ポート番号12345での接続を受け入れる準備ができました。 受け入れられた接続 |
図2 - POSIXベースのポスト17.1を受け入れる
この動作の違いが重要になることがあります。接続後にクライアントがサーバアプリケーションからの応答を期待している場合、アプリケーションが実際に accept を呼び出す前にタイムアウトして接続を閉じることがあります。
POSIXでアプリケーションを構築するには?最初の一行
#define _POSIX_C_SOURCE 200112L |
はアプリケーションのソースの最初の行でなければなりません。次にライブラリのパス
(master_disk)>system>posix_object_library
は、STCP ライブラリの後、C ライブラリの前のオブジェクト・ライブラリ・パスにある必要があります。
これが行われたかどうかはどうやってわかるのでしょうか?アプリケーションがバインドされているオブジェクトライブラリを見るには display_program_module -object_dirs コマンドを使います。
display_program_module acceptTestwithPosix -object_dir
%azvos#m17_mas>SysAdmin>Noah_Davids>temp>acceptTestwithPosix.pm
オブジェクトディレクトリマップ。
11の検索ディレクトリ
0 非検索ディレクトリ
全11件のディレクトリ
DTCディレクトリパス
1 %azvos#m17_mas>SysAdmin>Noah_Davids>temp
2 %azvos#m17_mas>system>stcp>object_library
3 %azvos#m17_mas>system>stcp>object_library>socket
4 %azvos#m17_mas>system>stcp>object_library>net
5 %azvos#m17_mas>system>stcp>object_library>common
6 %azvos#m17_mas>system>posix_object_library
7 %azvos#m17_mas>system>c_object_library
8 %azvos#m17_mas>system>object_library
9 %azvos#m17_mas>opt>apache>lib
10 %azvos#m17_mas>opt>openssl>lib
11 %azvos#m17_mas>opt>mysql>lib>mysql
|
しかし、これでは#defineがソースコードの一部であるかどうかはわかりません。
POSIX ベースのプログラムには SF_POSIX ソケットフラグが設定されています。例えば、私は acceptTestnoPosix、acceptTestwithPosix、acceptTestwithPosixPathOnly という 3 つのプログラムを持っています。この最後のプログラムは、ライブラリパスに >system>posix_object_library ディレクトリがありますが、ソースコードに #define が含まれていませんでした。これは無効な組み合わせとみなされることに注意してください。POSIX ライブラリにバインドされていて POSIX_SOURCE #define 文をコードに含んでいたアプリケーションだけが SF_POSIX フラグを持つソケットを作成しました。
acceptTestnoPosix.pm 12345 acceptTestnoPosix 12345 の実行 300秒睡眠 as: match posix; dump_stcbq -full -lport 12345 として。 |
acceptTestwithPosix.pm 12345
acceptTestnoPosix 12345 の実行
300秒睡眠
as: match posix; dump_stcbq -full -lport 12345
SF_POSIX
として。
|
acceptTestwithPosixPathOnly.pm 12345 acceptTestnoPosix 12345 の実行 300秒睡眠 as: match posix; dump_stcbq -full -lport 12345 として。 |
4つ目の可能性としては、#defineがソースに含まれていたがposix_object_libraryが使われていなかったということが考えられます。この場合、ソケットルーチンはエラーを返します。
acceptTestwithPosixDefineOnly 12345 acceptTestnoPosix 12345 の実行 acceptTestnoPosix: リスニングソケットを作成できません。ビルドされたアプリケーション + 不正確です。POSIXランタイムはCランタイムの前に検索されなければなりません。 |
STCPコマンドとユーティリティはすべてPOSIXで構築されており、構築するアプリケーションもPOSIXを使用することを強く推奨します。