socket_select
socket_select — 与えられたソケットの配列に対し、指定した有効時間で select() システムコールを実行する
説明
int socket_select ( array &read, array &write, array &except, int tv_sec [, int tv_usec] )socket_select() はソケットの配列を受け取り、 それらの状態が変化するまで待ちます。BSD のソケットについての 知識がある方なら、これらのソケットの配列が、いわゆるファイル記述子 セットであることがご理解いただけるでしょう。3 つの独立した 配列で、ソケットリソースが監視されます。
配列 read に挙げられたソケットでは、 文字が読み込み可能になっているかどうか(厳密に言うと、読み込みが ブロックされていないかどうか - 実際には、ソケット記述子はファイルの 終端でも有効です。そのような場合、socket_read() は長さゼロの文字列を返します)を監視します。
配列 write に挙げられたソケットでは、 書き込みがブロックされていないかどうかを監視します。
配列 except に挙げられたソケットでは、 例外を監視します。
警告 |
終了時に配列は書き換えられ、どのソケットの状態が変わったのかが
わかるようになります。
|
socket_select() のすべての配列を設定する必要は ありません。使用しないものについては空の配列や NULL をかわりに 指定しておくことが可能です。また、これらの配列は参照渡し であり、socket_select() をコールした後でその中身が 書き換えられていることに注意しましょう。
例 2152. socket_select() の例
<?php
/* 読み込み用の配列を準備する */
$read = array($socket1, $socket2);
$num_changed_sockets = socket_select($read, $write = NULL, $except = NULL, 0);
if ($num_changed_sockets === false) {
/* エラー処理 */
} else if ($num_changed_sockets > 0) {
/* すくなくともひとつのソケットで、何らかの出来事が起こっています */
}
?>
注意: 現状の Zend Engine の制限により、関数の参照渡しパラメータに NULL のような定数値を直接渡すことができません。一時的な 変数を使用するか、あるいは一番左に一時変数を使用する式を 使用してください。 例 2153. socket_select() での NULL の使用
<?php
socket_select($r, $w, $e = NULL, 0);
?>
tv_sec および tv_usec は、ともにタイムアウトを指定するパラメータです。 タイムアウトは、socket_select() が結果を返すまでの経過時間の最大値です。 tv_sec はゼロにすることも可能で、そうすると socket_select() は結果をすぐに返します。 これはポーリングをする際に有用です。tv_sec に NULL(タイムアウトしない)を指定すると、 socket_select() は無期限にブロックします。
成功した場合は、socket_select() は配列内で 変化のあったソケットリソースの数を返します。もし何かがおこる前に タイムアウト時間が経過した場合は、ゼロを返すことになります。 エラー時には FALSE が返されます。エラーコードは socket_last_error() で取得可能です。
注意: エラーかどうかを調べる際には、必ず === 演算子を 使用するようにしましょう。socket_select() は 0 を返す場合もあり、このような場合に == を用いて比較すると、エラーと判定されてしまいます。 例 2154. socket_select() の返す結果を知る
<?php
if (false === socket_select($r, $w, $e = NULL, 0)) {
echo "socket_select() は失敗しました。原因: " .
socket_strerror(socket_last_error()) . "\n";
}
?>
注意: ソケットの実装によっては、取り扱いに注意すべきものがあることを 知っておいてください。基本的なルールは以下のとおりです。
- 基本的に socket_select() のタイムアウトは 指定しないように心がけましょう。もしデータがなかった場合に、 プログラム側でそれを判定できなくなってしまいます。タイムアウトに 依存しているコードは移植性が悪く、デバッグが困難です。
- socket_select() のコール後に値をチェックして 適切に処理するつもりがないソケットリソースは、決して配列に追加 してはいけません。 socket_select() から値が返ってきたあとは、配列内の すべてのソケットリソースをチェックする必要があります。すべての書き込み用 ソケットは書き込める必要がありますし、またすべての読み込み用ソケットは 読み込める必要があります。
- 配列で返されたソケットに対して読み込み/書き込みをする場合には、 指定したデータを必ずしもすべて読み込み/書き込みするとは限らないことを 知っておいてください。たった 1 バイトしか読み込み/書き込みが できなかった場合にも対処できるよう準備しておきましょう。
- ほとんどのソケット実装で、except でキャッチできる 例外はただひとつ、すなわちソケットが受け取ったデータが帯域外で あったということだけです。
socket_read()、 socket_write()、 socket_last_error() および socket_strerror() も参照ください。
Socket.Select メソッド
アセンブリ: System (system.dll 内)

Public Shared Sub Select ( _ checkRead As IList, _ checkWrite As IList, _ checkError As IList, _ microSeconds As Integer _ )
Dim checkRead As IList Dim checkWrite As IList Dim checkError As IList Dim microSeconds As Integer Socket.Select(checkRead, checkWrite, checkError, microSeconds)
public: static void Select ( IList^ checkRead, IList^ checkWrite, IList^ checkError, int microSeconds )
public static function Select ( checkRead : IList, checkWrite : IList, checkError : IList, microSeconds : int )


Select は、1 つ以上の Socket インスタンスのステータスを決定する静的メソッドです。Select メソッドを使用するには、1 つ以上のソケットを IList に挿入する必要があります。ソケットが読み取り可能かどうかを確認するには、checkRead パラメータに IList を指定して Select を呼び出します。書き込み可能かどうかを確認するには、checkWrite パラメータを使用します。エラー条件を検出する場合は、checkError を使用します。Select を呼び出したら、IList には、その条件を満たすソケットだけが設定されます。
読み取り可能な状態では、待機状態の場合、Accept がブロックせずに正常に呼び出されます。接続を受け入れている場合は、読み取ることができるデータが存在することを意味します。いずれの場合も、すべての受信操作がブロックせずに正常に行われます。また、リモート Socket が接続をシャットダウンしているかどうかも示します。接続をシャットダウンしている場合は、Receive の実行がすぐに終了し、0 バイトが返されます。
少なくとも 1 つの関連するソケット (checkRead、checkWrite、および checkError の各リスト内のソケット) が指定した条件を満たしたか、または microSeconds パラメータが超過したかのいずれかが最初に発生したときに、Select から制御が戻ります。microSeconds を -1 に設定すると、無期限のタイムアウトが指定されます。
Connect を非ブロッキングで呼び出す場合、書き込み可能とは正常に接続が確立されていることを意味します。既に接続が確立されている場合は、すべての送信操作がブロックせずに正常に行われます。
Connect を非ブロッキングで呼び出した場合は、checkerror パラメータが正常に接続されていないソケットを特定します。
![]() |
---|

Select を使用し、待機中のどのソケットが接続を要求しているかを判断するコード例を次に示します。
Dim ipHostEntry As IPHostEntry = Dns.Resolve(Dns.GetHostName()) Dim ipAddress As IPAddress = ipHostEntry.AddressList(0) Dim socket0 As Socket = Nothing Dim socket1 As Socket = Nothing Dim socket2 As Socket = Nothing Dim socket3 As Socket = Nothing Dim socket4 As Socket = Nothing Dim socket5 As Socket = Nothing Dim listenList As New ArrayList() listenList.Add(socket0) listenList.Add(socket1) listenList.Add(socket2) Dim acceptList As New ArrayList() acceptList.Add(socket3) acceptList.Add(socket4) acceptList.Add(socket5) Dim i As Integer For i = 0 To 2 listenList(i) = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) CType(listenList(i), Socket).Bind(New IPEndPoint(ipAddress, 11000 + i)) CType(listenList(i), Socket).Listen(10) Next i 'Only the sockets that contain a connection request 'will remain in listenList after Select returns. Socket.Select(listenList, Nothing, Nothing, 1000) For i = 0 To listenList.Count - 1 acceptList(i) = CType(listenList(i), Socket).Accept() Next i
IPHostEntry ipHostEntry = Dns.Resolve(Dns.GetHostName()); IPAddress ipAddress = ipHostEntry.AddressList[0]; Socket socket0 = null; Socket socket1 = null; Socket socket2 = null; Socket socket3 = null; Socket socket4 = null; Socket socket5 = null; ArrayList listenList = new ArrayList(); listenList.Add(socket0); listenList.Add(socket1); listenList.Add(socket2); ArrayList acceptList = new ArrayList(); acceptList.Add(socket3); acceptList.Add(socket4); acceptList.Add(socket5); for( int i = 0; i < 3; i++ ) { listenList[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ((Socket)listenList[i]).Bind(new IPEndPoint(ipAddress, 11000 + i)); ((Socket)listenList[i]).Listen(10); } // Only the sockets that contain a connection request // will remain in listenList after Select returns. Socket.Select(listenList, null, null, 1000); for( int i = 0; i < listenList.Count; i++ ) { acceptList[i] = ((Socket)listenList[i]).Accept(); }
IPHostEntry^ lipa = Dns::Resolve( Dns::GetHostName() ); //Gets three separate local endpoints. IPEndPoint^ lep1 = gcnew IPEndPoint( lipa->AddressList[ 0 ],11000 ); IPEndPoint^ lep2 = gcnew IPEndPoint( lipa->AddressList[ 0 ],11001 ); IPEndPoint^ lep3 = gcnew IPEndPoint( lipa->AddressList[ 0 ],11002 ); //creates an array of endpoints. array<IPEndPoint^>^ipendpoints = gcnew array<IPEndPoint^>(3); ipendpoints[ 0 ] = lep1; ipendpoints[ 1 ] = lep2; ipendpoints[ 2 ] = lep3; //Creates three separate sockets. Socket^ s1 = gcnew Socket( lep1->Address->AddressFamily,SocketType::Stream,ProtocolType::Tcp ); Socket^ s2 = gcnew Socket( lep2->Address->AddressFamily,SocketType::Stream,ProtocolType::Tcp ); Socket^ s3 = gcnew Socket( lep3->Address->AddressFamily,SocketType::Stream,ProtocolType::Tcp ); array<Socket^>^socketList = gcnew array<Socket^>(3); socketList[ 0 ] = s1; socketList[ 1 ] = s2; socketList[ 2 ] = s3; //Binds and Listens on all sockets in the array of sockets. for ( int i = 0; i < 3; i++ ) { socketList[ i ]->Bind( ipendpoints[ i ] ); socketList[ i ]->Listen( 1000 ); } //Calls Select to determine which sockets are ready for reading. Socket::Select( safe_cast<IList^>(socketList), nullptr, nullptr, 1000 ); //Reads on the sockets returned by Select. array<Byte>^buffer = gcnew array<Byte>(1024); String^ outString; for ( Int32 j = 0; j < (socketList->Length - 1); j++ ) { socketList[ j ]->Receive( buffer ); outString = "Socket "; outString->Concat( j.ToString(), " has the message", Encoding::ASCII->GetString( buffer ) ); Console::WriteLine( outString ); } } }; int main() { return 0; }
IPHostEntry ipHostEntry = Dns.Resolve(Dns.GetHostName()); IPAddress ipAddress = ipHostEntry.get_AddressList()[0]; Socket socket0 = null; Socket socket1 = null; Socket socket2 = null; Socket socket3 = null; Socket socket4 = null; Socket socket5 = null; ArrayList listenList = new ArrayList(); listenList.Add(socket0); listenList.Add(socket1); listenList.Add(socket2); ArrayList acceptList = new ArrayList(); acceptList.Add(socket3); acceptList.Add(socket4); acceptList.Add(socket5); for (int i = 0; i < 3; i++) { listenList.set_Item(i, new Socket(AddressFamily.InterNetwork , SocketType.Stream, ProtocolType.Tcp)); ((Socket)listenList.get_Item(i)). Bind(new IPEndPoint(ipAddress, 11000 + i)); ((Socket)listenList.get_Item(i)).Listen(10); } // Only the sockets that contain a connection request // will remain in listenList after Select returns. Socket.Select(listenList, null, null, 1000); for (int i = 0; i < listenList.get_Count(); i++) { acceptList.set_Item(i, ((Socket)listenList.get_Item(i)).Accept()); }

Windows 98, Windows 2000 SP4, Windows CE, Windows Millennium Edition, Windows Mobile for Pocket PC, Windows Mobile for Smartphone, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition
開発プラットフォームの中には、.NET Framework によってサポートされていないバージョンがあります。サポートされているバージョンについては、「システム要件」を参照してください。


- socketselectのページへのリンク