socket_set_blockは、ソケットをブロッキングモードに設定するPHPソケット拡張機能の関数です。いわゆるブロッキングモードは、読み取り操作を実行するときに、データの準備ができていない場合、プログラムは実行され続ける前にデータの準備ができるまで待機します。比較的、データの準備ができているかどうかに関係なく、非ブロッキングモードはすぐに戻ります。
ブロッキングモードは、データが読み取られたときに何も見逃されないことを保証し、データの整合性を実現するのに役立ちます。
bool socket_set_block ( resource $socket )
この関数のパラメーターはソケットリソースです。コールは成功後に真実であり、失敗後にfalseを返します。
データを読み取ると、ソケットがブロックしている場合、 Socket_readはデータが読み取られるか、接続が閉じられるまで待機します。ループの読み取りと長さの判断を組み合わせることにより、すべてのデータがそのまま読み取られるようにすることができます。
一般的なアイデアは次のとおりです。
ソケットをブロッキングモードに設定します。
データは、予想されるバイト数が読み取られるか、接続が切断されるまでループを継続的に読み取ります。
すべての読み取りデータをスプライスして、データが完了していることを確認します。
Socket_set_blockを使用してデータの整合性を確保する方法を示す簡単なクライアント側の読み取りデータ例を以下に示します。
<?php
$host = "gitbox.net";
$port = 8080;
// 作成する TCP ソケット
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("socket_create failed: " . socket_strerror(socket_last_error()));
}
// サーバーに接続します
if (!socket_connect($socket, $host, $port)) {
die("socket_connect failed: " . socket_strerror(socket_last_error($socket)));
}
// ブロッキングモードを設定します,確認する socket_read データを待っているブロック
socket_set_block($socket);
$totalData = '';
$expectedLength = 1024; // 読むことを期待しているとします 1024 バイトデータ
$bytesRead = 0;
while ($bytesRead < $expectedLength) {
$buffer = socket_read($socket, $expectedLength - $bytesRead);
if ($buffer === false) {
die("socket_read failed: " . socket_strerror(socket_last_error($socket)));
}
if ($buffer === '') {
// 接続が閉じます
break;
}
$totalData .= $buffer;
$bytesRead += strlen($buffer);
}
// 关闭ソケット
socket_close($socket);
// 完全なデータを出力します
echo "完全なデータを受け取りました:\n";
echo $totalData;
?>
最初にSocket_Createを使用してTCPソケットを作成します。
サーバーに接続すると、アドレス内のドメイン名がgitbox.netに置き換えられます。
socket_set_blockを使用して、ソケットをブロッキングモードに設定します。
ループを入力して、予想されるバイト数が読み取られるか、接続が閉じられるまでデータを読み取ります。
読み取りデータは、データが失われないように$ TotalDataにスプライスされています。
最後に、完全なデータが出力されます。
ブロッキングモードにより、プログラムは一時停止し、読み取り中に待機します。ネットワークが不安定な場合、プログラムはゆっくりと応答する場合があります。実際のアプリケーションで適切なタイムアウトを設定することをお勧めします。
データを読み取るときは、データ境界をプロトコル設計に従って審査する必要があります。この例では、固定長の読み取り値が想定されています。
より複雑なプロトコルの場合、データパケットヘッダーと組み合わせて長さを定義し、最初にパケットヘッダーを読み取り、次に対応する長さのコンテンツを読み取ることができます。