from: http://www.phppan.com/2011/02/php-socket/
PHP ソケット プログラミング
コンピューター プロセスは、ソケット (他のプロセスの場所) を介して他のプロセスと通信できます。透明です。これらのプロセスは、同じコンピュータ上に存在することも、異なるコンピュータ上に存在することもできます。
PHPでは拡張機能としてソケットが読み込まれていますが、ソケット関連の機能が使用できない場合は、この拡張機能がオンになっているか確認してください。
以下では、接続指向のクライアントとサーバーの簡単な実装でいくつかの関数の使用法を説明します。その後、これらの関数が PHP 内でどのように実装されるかを簡単に紹介します。
【クライアント実装】
以下に示すコードはクライアント実装コードです:
set_time_limit(0); $host = "127.0.0.1";$port = 2046; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)or die("Could not create socket\n"); // 创建一个Socket $connection = socket_connect($socket, $host, $port) or die("Could not connet server\n"); // 连接 socket_write($socket, "time") or die("Write failed\n"); // 数据传送 向服务器发送消息 while ($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)) { echo("Data sent was: time\nResponse was:" . $buffer . "\n");} socket_close($socket);
クライアントはまずソケットを作成し、サーバーに接続します。サーバーに時刻メッセージを送信し、サーバーから情報が返されるのを待ち、サーバー情報を読み取って出力します。
【サーバー実装】
set_time_limit(0); $host = "127.0.0.1";$port = 2046; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n"); // 创建一个Socket $result = socket_bind($socket, $host, $port) or die("Could not bind tosocket\n"); //绑定Socket到端口 $result = socket_listen($socket, 3) or die("Could not set up socket listener\n"); // 开始监听连接 $spawn = socket_accept($socket) or die("Could not accept incoming connection\n"); // 处理通信 $input = socket_read($spawn, 1024) or die("Could not read input\n"); // 数据传送 获得客户端的输入 $input = trim($input);echo 'input:', $input, "\n"; if ($input == 'time') { $output = date("Y-m-d H:i:s"). "\n"; //处理客户端输入并返回结果}else{ $output = "input error \n"; //处理客户端输入并返回结果} echo "output:", $output, "\n"; // 数据传送 向客户端写入返回结果socket_write($spawn, $output, strlen($output)) or die("Could not write output\n"); // 关闭socketssocket_close($spawn);socket_close($socket);
サーバーはソケットを作成し、ポートをバインドし、接続をリッスンし、クライアントのデータを読み取り、クライアントの入力に基づいてさまざまな値を返し、最後にデータを書き込みますクライアント。ソケットを閉じます。
このサーバーは複数の接続を受け入れることができず、1 つの操作のみを完了するだけです
[PHP 内部ソース コードの説明]
PHP 内部ソース コードから、PHP が提供するソケット プログラミングは、ソケット、バインド、リッスン、その他の機能にレイヤーを追加します、よりシンプルで簡単に呼び出すことができます。ただし、一部のビジネス ロジック プログラムは依然としてプログラマー自身が実装する必要があります。
以下では、socket_create のソース コード実装を使用して、PHP の内部実装を説明します。
先ほど、PHP ソケットは拡張された方法で実装されると述べました。ソース コードの ext ディレクトリに、socket ディレクトリがあります。このディレクトリには、PHP のソケット実装が保存されます。 PHP_FUNCTION(socket_create) を直接検索し、socket.c ファイル内でこの関数の実装を見つけます。コードは次のとおりです。
/* {{{ proto resource socket_create(int domain, int type, int protocol) U Creates an endpoint for communication in the domain specified by domain, of type specified by type */PHP_FUNCTION(socket_create){ long arg1, arg2, arg3; php_socket *php_sock = (php_socket*)emalloc(sizeof(php_socket)); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &arg1, &arg2, &arg3) == FAILURE) { efree(php_sock); return; } if (arg1 != AF_UNIX#if HAVE_IPV6 && arg1 != AF_INET6#endif && arg1 != AF_INET) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", arg1); arg1 = AF_INET; } if (arg2 > 10) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", arg2); arg2 = SOCK_STREAM; } php_sock->bsd_socket = socket(arg1, arg2, arg3); php_sock->type = arg1; if (IS_INVALID_SOCKET(php_sock)) { SOCKETS_G(last_error) = errno; php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create socket [%d]: %s", errno, php_strerror(errno TSRMLS_CC)); efree(php_sock); RETURN_FALSE; } php_sock->error = 0; php_sock->blocking = 1; 1257,1-8 61% ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);}/* }}} */
関数全体の実装から、プログラムは基本的にエラーと例外の処理です。 PHP 自体は php_socket 構造を導入しており、作成時にソケット関数を呼び出すことで実装されます。
追記: PHP ネットワークプログラミングについては、TIPI シリーズの記事で詳しく説明します。
[ソケット関数]
関数名の説明
socket_accept()はソケット接続を受け入れます
socket_bind()はソケットをIPアドレスとポートにバインドします
socket_clear_error()はソケットエラーまたは最後のエラーコードをクリアします
socket_close()はソケットリソースを閉じます
socket_connect()はソケット接続を開始します
socket_create_listen()は指定されたポートでリッスンするソケットを開きます
socket_create_pair()は未分化ソケットのペアを配列に生成します
socket_create()はソケットを生成します。これはソケットの生成と同等です データ構造
socket_get_option() ソケットオプションを取得します
socket_getpeername() リモートの同様のホストの IP アドレスを取得します
socket_getsockname() ローカルソケットの IP アドレスを取得します
socket_iovec_add() 新しいベクトルを分散/集約配列に追加します
ソケット_iovec_alloc( )この関数は、送信、受信、読み取り、書き込みができる iovec データ構造を作成します
socket_iovec_delete() は、割り当てられた iovec を削除します
socket_iovec_fetch() は、指定された iovec リソースのデータを返します
socket_iovec_free() は、iovec リソースを解放します
socket_iovec_set() は、 iovec 新しいデータ値
socket_last_error() 現在のソケットの最後のエラー コードを取得します
socket_listen() は指定されたソケットからのすべての接続をリッスンします
socket_read() は指定された長さのデータを読み取ります
socket_readv() は分散/集約からデータを読み取ります配列
socket_recv() ソケットからキャッシュへのデータを終了します
socket_recvfrom()は指定されたソケットからデータを受け取ります、指定されていない場合は、現在のソケットがデフォルトになります
socket_recvmsg()はiovecからメッセージを受け取ります
socket_select()複数選択
socket_send( ) この関数 接続されているソケットにデータを送信
socket_sendmsg() ソケットにメッセージを送信
socket_sendto() 指定したアドレスのソケットにメッセージを送信
socket_set_block() ソケットをブロックモードに設定
socket_set_nonblock() ソケットを設定ノンブロックモードへ
socket_set_option() ソケットオプションを設定します
socket_shutdown() この関数を使用すると、読み取り、書き込み、または指定されたソケットを閉じることができます
socket_strerror() 指定されたエラー番号を持つ詳細なエラーを返します
socket_write() データを書き込みますソケットキャッシュ
socket_writev() データをディスク /aggregate 配列に書き込みます