ホームページ > バックエンド開発 > PHPチュートリアル > PHP で fsockopen を使用して非同期リクエストを実装する (コード例)

PHP で fsockopen を使用して非同期リクエストを実装する (コード例)

藏色散人
リリース: 2023-04-08 09:40:02
転載
3136 人が閲覧しました

PHP で fsockopen を使用して非同期リクエストを実装する (コード例)

php はプログラムを実行しますが、数ミリ秒で完了する場合もあれば、長時間かかる場合もあります。

たとえば、ユーザーが注文を行う場合、電子メール、テキスト メッセージ、プッシュ通知などを送信するために一部のサードパーティ サービスが呼び出される場合、フロントエンドは待たされる可能性があります。

これらの時間のかかるスクリプトは、実行される限り、戻り結果を気にしないことがあります。このとき、非同期で実行する必要があります。

ご存知のとおり、PHP はマルチスレッドを直接サポートしていません。妥協した方法でそれを行うこともできます。ここで重要なのは fsockopen です。

fsockopen を通じてリクエストを送信し、返された結果を無視すると、プログラムはすぐに戻ることができます。

サンプル コード:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);

if (!$fp) {

    echo "$errstr ($errno)<br />\n";

} else {

    $out = "GET /backend.php   HTTP/1.1\r\n";

    $out .= "Host: www.example.com\r\n";

    $out .= "Connection: Close\r\n\r\n";

  

    fwrite($fp, $out);

    /*忽略执行结果

    while (!feof($fp)) {

        echo fgets($fp, 128);

    }*/

    fclose($fp);

}

ログイン後にコピー

ヘッダー情報を手動で入力する必要があることに注意してください。コメントセクションを開くと、リクエストの戻り結果が表示されますが、プログラムは戻り結果を待って終了するため、今回は再び同期になります。

実際にテストしてみたところ、実行結果を無視しなければデバッグ時に毎回sockリクエストは正常に送信されるのですが、実行結果を無視するとsockリクエストが送信されないことが多いことが分かりました。成功しました。 nginx ログを確認すると、ステータス コード 499 のリクエストが多数見つかります。

後で理由がわかりました。

fwritefclose の直後に実行され、nginx は直接 499 を返します。リクエストは処理のために php に転送されます。

クライアントがアクティブ ポートを介して接続をリクエストした場合、NGINX はリクエストを上流のサービス (FastCGI PHP プロセス) にプロキシしません。このとき、リクエストはアクセス ログに 499 として記録されます。

解決策:

1) nginx.conf に構成を追加します。

1

2

# 忽略客户端中断

fastcgi_ignore_client_abort on;

ログイン後にコピー

2) fwrite の後に usleep を使用します。関数は 20 ミリ秒スリープします:

1

usleep(20000);

ログイン後にコピー

その後のテストでは障害は見つかりませんでした。

完全なコードを添付します:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

<?php

/**

 * 工具类

 * */

class FsockService {

     

    public static function post($url, $param){

        $host = parse_url($url, PHP_URL_HOST);

        $port = 80;

        $errno = &#39;&#39;;

        $errstr = &#39;&#39;;

        $timeout = 30;

        $data = http_build_query($param);

        // create connect

        $fp = fsockopen($host, $port, $errno, $errstr, $timeout);

        if(!$fp){

            return false;

        }

        // send request

        $out = "POST ${url} HTTP/1.1\r\n";

        $out .= "Host:${host}\r\n";

        $out .= "Content-type:application/x-www-form-urlencoded\r\n";

        $out .= "Content-length:".strlen($data)."\r\n";

        $out .= "Connection:close\r\n\r\n";

        $out .= "${data}";

        fwrite($fp, $out);

        //忽略执行结果;否则等待返回结果

//        if(APP_DEBUG === true){

        if(false){

            $ret = &#39;&#39;;

            while (!feof($fp)) {

                $ret .= fgets($fp, 128);

            }

        }

        usleep(20000); //fwrite之后马上执行fclose,nginx会直接返回499

        fclose($fp);

    }

    public static function get($url, $param){

        $host = parse_url($url, PHP_URL_HOST);

        $port = 80;

        $errno = &#39;&#39;;

        $errstr = &#39;&#39;;

        $timeout = 30;

        $url = $url.&#39;?&#39;.http_build_query($param);

        // create connect

        $fp = fsockopen($host, $port, $errno, $errstr, $timeout);

        if(!$fp){

            return false;

        }

        // send request

        $out = "GET ${url} HTTP/1.1\r\n";

        $out .= "Host:${host}\r\n";

        $out .= "Connection:close\r\n\r\n";

        fwrite($fp, $out);

        //忽略执行结果;否则等待返回结果

//        if(APP_DEBUG === true){

        if(false){

            $ret = &#39;&#39;;

            while (!feof($fp)) {

                $ret .= fgets($fp, 128);

            }

        }

        usleep(20000); //fwrite之后马上执行fclose,nginx会直接返回499

        fclose($fp);

    }

    

}

?>

ログイン後にコピー

関連する php の知識については、php チュートリアル をご覧ください。

以上がPHP で fsockopen を使用して非同期リクエストを実装する (コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート