ホームページ  >  記事  >  バックエンド開発  >  PHPソケットプログラミング

PHPソケットプログラミング

高洛峰
高洛峰オリジナル
2016-11-19 10:31:35834ブラウズ

PHP ソケット プログラミングは理解するのが比較的難しいですが、いくつかのソケット関数とそれらが果たす役割の関係を理解する限り、ソケット プログラミングを理解するのは難しいことではありません。ネットワーク サービスのクライアントとサーバーを確立します。これは、mysql のクライアントとサーバーが何であるかを理解していれば、次のことを理解できるはずです。 。

TCP、UDP、ソケットスリーウェイハンドシェイクなど、ソケットプログラミングに関連するネットワークプロトコルについては、インターネット上に非常に詳細な説明がありますので、ここでは説明しません。ソケットを確立するプロセスのスクリーンショットを撮ってください:

PHPソケットプログラミング

私はこの写真を他の人から盗むために一生懸命働きました。同時に、私もそれをよく見てください。スクリーンショットを盗まれた作者に感謝します。パターンを盗用したことをお詫びします。気にしないでください。絵を描くのがめんどくさい(というか絵に自信がないということです笑)。

ソケットはどのように接続を確立するのでしょうか?上で述べたように、接続を確立するプロセスは、mysql クライアントとサーバー間の接続と基本的に同じです。 mysql との違いは、mysql のサーバーとクライアントが編集されており、それを適用するだけでよいということです。しかし、重大な瞬間が来ました。Socket が提供するのは、数十のソケット機能だけです。

これが意味するのは、ソケットプログラミングではサーバーとクライアントを自分で作成する必要がある、つまり「ソケットプログラミング」、つまりmysqlに似たサーバーとクライアントのアプリケーションを構築する必要があるということです。

そうは言っても、お聞きしたいのですが、このソケットは頭痛を引き起こすと思いますか?適用するサーバーもクライアントも作成しません。ソケット関数を使用して、独自のネットワーク プロトコル ソケット アプリケーションを作成する必要があります。独自のアプリケーションが必要な場合でも、ソケットを扱う必要があります。あはは、これは単なる余談ですので、多くは言いませんが、本題に入りましょう。

ソケットプログラミングに混乱する前に、ソケットのいくつかの主要な機能を見て、それぞれの機能を最初に説明します。そうしないと、ソケット プログラミングの基礎がまったくない人がこれを読むと、読み終わった後、この記事を思い切って読み飛ばして、今後ソケット恐怖症になってしまうのではないかと思います。ハハ、もっと言ってよ。

ソケットのキー関数1:

socket_create($netパラメータ1, $streamパラメータ2, $protocolパラメータ3)

機能: 端的に言えば、ソケットソケットを作成します。

戻り値: ソケット、または false、パラメータが間違っている場合は E_WARNING 警告が発行されます

PHP オンラインマニュアルでは、より明確に説明されています:

socket_create は、通信ノードとも呼ばれるソケットを作成して返します。一般的なネットワーク接続は 2 つのソケットで構成され、1 つはクライアント側で実行され、もう 1 つはサーバー側で実行されます。

上記の文はphpオンラインマニュアルからコピーしました。ここでの意味は、上で繰り返し述べたクライアントとサーバーとまったく同じであることがわかりましたか?ふふ。

パラメータ1は:ネットワークプロトコル、

ネットワークプロトコルとは何ですか?オプションは次の 3 つです。 AF_INET: IPv4 ネットワーク プロトコル。 TCP と UDP の両方がこのプロトコルを使用できます。これは一般的に使用されます。

AF_INET6: IPv6 ネットワークプロトコル。 TCP と UDP の両方がこのプロトコルを使用できます。

AF_UNIX: ローカル通信プロトコル。高性能かつ低コストの IPC (プロセス間通信)。

パラメータ2:ソケットストリーム、オプションは:

SOCK_STREAM SOCK_DGRAM SOCK_SEQPACKET SOCK_RAW SOCK_RDM。

ここでは最初の 2 つだけを説明します:

SOCK_STREAM TCP プロトコルソケット。

SOCK_DGRAM UDPプロトコルソケット。

詳細については、ここにリンクしてください: http://php.net/manual/zh/function.socket-create.php

パラメータ 3: プロトコル プロトコル、オプションは:

SOL_TCP: TCP プロトコル。

SOL_UDP: UDPプロトコル。

ここから、socket_create関数の2番目のパラメータと3番目のパラメータが実際に関連していることがわかります。

例えば、最初のパラメータが IPv4 プロトコル: AF_INET を使用し、次に 2 番目のパラメータが TCP ソケット: SOCK_STREAM を使用する場合、

3 番目のパラメータは SOL_TCP を使用する必要がありますが、これは理解するのが難しくありません。

TCPプロトコルのソケットに関しては、当然TCPプロトコルしか使えませんよね? UDP ソケットを使用する場合、3 番目のパラメータの選択方法については説明しません (笑)。

キー関数2:

socket_connect($socketパラメータ1, $ipパラメータ2, $portパラメータ3)

関数:ソケットを接続、戻り値はtrueかfalseです

パラメータ1:socket_create Function return value

sinceCE in in in in in_in Aソケット、戻り値はtrueかfalseです

パラメータ1:socket_createの関数戻り値

パラメータ2: ipアドレス

パラメータ3:ポート番号

キー機能4:

socket_listen($sock etparameters 1,$backlog Parameter 2)

関数: ソケットをリッスン、戻り値は true または false です

パラメータ 1:socket_create の関数の戻り値

パラメータ 2:待機ソケットの最大数

キー関数 5:

socket_accept($socket)

rine in in in in>> :

socket_read($socket)

機能:ソケットのリソース情報を読み込み、

戻り値:ソケットリソースの文字列情報への変換成功、失敗はfalse

パラメータ:socket_createまたはsocket_accept 関数戻り値

キー関数7:

socket_write($socketパラメータ1, $msgパラメータ2, $ strlenパラメータ3)

関数:ソケットにデータを書き込む

戻り値:成功は文字列を返す 文字列のバイト長、失敗はfalse

パラメータ:socket_createまたはsocket_acceptの関数戻り値

キー関数8:

socket_close($socket)

関数:ソケットを閉じる

戻り値:成功時はtrueを返し、失敗時はfalse

パラメータ:socket_createまたはsocket_acceptの関数戻り値

これら8つの関数がsocketの中核となる関数です. さらに重要な関数が2つあります

socket_last_error($socket)、パラメータはsocket_create 戻り値はソケットコード

socket_strerror($code)です。はsocket_last_error関数の戻り値です コードの文字列情報を取得します 戻り値はソケットエラーメッセージです

ソケットプログラミングを書く際には、やはりこの2つの関数を活用する必要があると思います。特に初心者向けに、デバッグに使用できます

以下はコードです、注意してください、私のコメントを注意深く読んでください、コメントは非常に重要です、コメントは非常に重要です、重要なことはそうあるべきです。と3回叫んだ(笑)。

サーバーサイドスクリプト、D:vhosttestsocketserver_socket.php

<?php
//创建服务端的socket套接流,net协议为IPv4,protocol协议为TCP
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);

    /*绑定接收的套接流主机和端口,与客户端相对应*/
    if(socket_bind($socket,&#39;127.0.0.1&#39;,8888) == false){
        echo &#39;server bind fail:&#39;.socket_strerror(socket_last_error());
        /*这里的127.0.0.1是在本地主机测试,你如果有多台电脑,可以写IP地址*/
    }
    //监听套接流
    if(socket_listen($socket,4)==false){
        echo &#39;server listen fail:&#39;.socket_strerror(socket_last_error());
    }
//让服务器无限获取客户端传过来的信息
do{
    /*接收客户端传过来的信息*/
    $accept_resource = socket_accept($socket);
    /*socket_accept的作用就是接受socket_bind()所绑定的主机发过来的套接流*/

    if($accept_resource !== false){
        /*读取客户端传过来的资源,并转化为字符串*/
        $string = socket_read($accept_resource,1024);
        /*socket_read的作用就是读出socket_accept()的资源并把它转化为字符串*/

        echo &#39;server receive is :&#39;.$string.PHP_EOL;//PHP_EOL为php的换行预定义常量
        if($string != false){
            $return_client = &#39;server receive is : &#39;.$string.PHP_EOL;
            /*向socket_accept的套接流写入信息,也就是回馈信息给socket_bind()所绑定的主机客户端*/
            socket_write($accept_resource,$return_client,strlen($return_client));
            /*socket_write的作用是向socket_create的套接流写入信息,或者向socket_accept的套接流写入信息*/
        }else{
            echo &#39;socket_read is fail&#39;;
        }
    /*socket_close的作用是关闭socket_create()或者socket_accept()所建立的套接流*/
        socket_close($accept_resource);
    }
}while(true);
socket_close($socket);

クライアントサイドスクリプト、D:vhosttestsocketclient_socket.php

<?php
    //创建一个socket套接流
    $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
    /****************设置socket连接选项,这两个步骤你可以省略*************/
     //接收套接流的最大超时时间1秒,后面是微秒单位超时时间,设置为零,表示不管它
    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 1, "usec" => 0));
     //发送套接流的最大超时时间为6秒
    socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 6, "usec" => 0));
    /****************设置socket连接选项,这两个步骤你可以省略*************/

    //连接服务端的套接流,这一步就是使客户端与服务器端的套接流建立联系
    if(socket_connect($socket,&#39;127.0.0.1&#39;,8888) == false){
        echo &#39;connect fail massege:&#39;.socket_strerror(socket_last_error());
    }else{
        $message = &#39;l love you 我爱你 socket&#39;;
        //转为GBK编码,处理乱码问题,这要看你的编码情况而定,每个人的编码都不同
        $message = mb_convert_encoding($message,&#39;GBK&#39;,&#39;UTF-8&#39;);
        //向服务端写入字符串信息

        if(socket_write($socket,$message,strlen($message)) == false){
            echo &#39;fail to write&#39;.socket_strerror(socket_last_error());

        }else{
            echo &#39;client write success&#39;.PHP_EOL;
            //读取服务端返回来的套接流信息
            while($callback = socket_read($socket,1024)){
                echo &#39;server return message is:&#39;.PHP_EOL.$callback;
            }
        }
    }
    socket_close($socket);//工作完毕,关闭套接流

これら2つのスクリプトをテストするにはどうすればよいでしょうか?

まず Windows DOS ウィンドウ、つまり cmd の黒いウィンドウを開いてから、php D:vhosttestsocketserver_socket.php,を実行します

サーバー側の黒いウィンドウを実行し続けます

次に、PHP クライアントスクリプトを実行できますブラウザ経由で、別の cmd black window を開いて

php D:vhosttestsocketclient_socket.php

ここで注意してください: 追加方法がわからない場合は、php 実行名を Windows 環境変数に追加する必要があります。それ、

php実行コマンドを入力してください 絶対コマンドでディレクトリを実行するか、Baiduの環境変数にphpコマンドを追加することもできます

これは私の状況です、あなたのファイルアドレスは私のものと異なる可能性があります、に従って操作してくださいあなたのアドレスに、そうでなければ、その結果はあなたが責任を負います、笑

上で述べたように、ソケットプログラミングでは通信するためにサーバーが必要なので、サーバー上の黒いウィンドウを開いたままにしておく必要があります。

追記補足:

socket_set_option ($socket パラメータ 1, $level パラメータ 2, $optname パラメータ 3, $optval パラメータ 4)

この関数の機能は、ソケットのデータ フロー オプションを設定することです。は今でも非常に重要な機能です。 Parameter 1:socket_createまたはsocket_accept

parameter2の関数戻り値:

SO_REUSEADDR ソケットポートを解放後すぐに再度使用できるようにするためのものです

パラメータ3がこれであれば、パラメータ4はtrueでもfalseでも構いません

SO_RCVTIMEO ソケットの受信リソースの最大タイムアウト時間です

SO_SNDTIMEO はい ソケットの送信リソースの最大タイムアウト

パラメータ3がこの2つなら、パラメータ4はこのarray('sec'=>1,'usec'=>500000)のような配列になります

それらはすべて最大タイムアウト時間を設定します。ただし、一方は秒単位で、もう一方はマイクロ秒単位で設定します


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:PHP の学習要件次の記事:PHP の学習要件