ホームページ  >  記事  >  バックエンド開発  >  PHPでのソケットプログラミングの詳しい説明

PHPでのソケットプログラミングの詳しい説明

高洛峰
高洛峰オリジナル
2016-12-12 09:41:191382ブラウズ

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の関数の戻り値

3: ポート番号

× キー関数 3:

×ソケットバインド($socket パラメータ 1, $ip パラメータ 2, $port パラメータ 3)

× 機能:ソケットをバインドし、戻り値はtrueかfalseです

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

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

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

キー関数4:

socket_listen($socketパラメータ1, $backlog パラメータ 2 )

関数: ソケットを監視し、戻り値は true または false

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

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

キー関数 5:

socket_accept( $socket)

関数:ソケットリソース情報を受信、ソケット情報リソースを正常に返却、失敗はfalse

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

キー関数6:

socket_read($socketパラメータ1, $lengthパラメータ2 )

関数: ソケットのリソース情報を読み取り、

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

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

パラメータ2:読み取った文字列

キー関数7:

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

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

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

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

」 成功した場合は文字列のバイト長が返されます

Socket_Close ($ ソケット)

: Close Set Piece

戻り値: TRUE、False に正常に戻ります

パラメーター: Socket_create または Socket_accept 、さらに 2 つの重要な関数を以下に示します

socket_last_error($socket)、パラメーターは、その関数であるsocket_create の戻り値です。はソケットの最後のエラーコード番号を取得するもので、戻り値はソケットコード

socket_strerror($code)、パラメータはsocket_last_error関数の戻り値、コードの文字列情報を取得します。戻り値はソケットのエラーメッセージでもあります。これらの 2 つの関数は、ソケットプログラミングを作成する場合、特に初心者にとってはデバッグに使用する必要があると思います

サーバーサイドスクリプト、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);

socket_bindのover through forward 、socket_listen関数とsocket_accept関数を実行した後のみ、socket_accept

クライアントスクリプト、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($socketparameter1,$levelparameter2,$optnameparameter3,$optvalparameter4)

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

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

パラメータ2:SOL_SOCKET、このオプションだけのようです

パラメータ3がパラメータ4に関係するのは、

パラメータ3はSO_REUSEADDR SO_RCVTIMEO S0_SNDTIMEO

説明してください:

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

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

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

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

パラメータ 3 がこれら 2 つの場合、パラメータ 4 は配列 array ('sec'=>1,'usec'=>500000) です

最大タイムアウト時間は配列に設定されていますが、一方は秒単位、もう一方はマイクロ秒単位であり、効果は同じです


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