検索

PHPでのソケット通信の詳細説明

Mar 16, 2018 am 11:34 AM
phpsocketコミュニケーション

場合によっては、PHP プログラムが他のシステムと通信する必要がある場合があります。たとえば、企業の公式 Web サイトでは、製品のトレーサビリティ情報の照会が行われ、その際、PHP ネットワーク プログラミングが必要になります。 PHP はソケット拡張機能を提供します。公式 Web サイトのアドレスは次のとおりです:

http://nl3.php.net/manual/zh/intro.sockets.php

この拡張機能により、ソケットを直接操作できるようになります。 php 経由で他のシステムと通信できるようにソケットに接続します。ソケットを使用して OSI ネットワーク モデルのトランスポート層の上で動作し、TCP および UDP によって提供されるサービスを直接使用します。そのため、他のシステムのクライアントとして使用できます。 HTTP クライアント (ブラウザ)、一般的な smtp、pop、ftp などのアプリケーション層プロトコルをシミュレートできます。さらに興味深いのは、これらのプロトコルはすべてアプリケーション層です。したがって、システム間の通信にはカスタム プロトコルが必要です。

ここでは、PHP を使用して単純なファイル受信サーバーを開発する例を示します。別の PHP クライアント プログラムは、このサーバー プログラムと通信する方法を示しています。コードは次のとおりです。

サーバー側プログラム:

<?php
/**
 * 本程序演示php网络编程:socket通讯 需要php开启php_sockets扩展
 * 这是一个简易的服务器程序,接收客户端发送的文件,保存后关闭
 * 通讯协议约定为:文件大小::文件扩展名::有效数据
 * 通讯结束标识符为:“-end-”
 * 在命令行或浏览器中执行均可,推荐命令行
 * 作者:云客【云游天下,作客四方】
 */

/****配置****/
//要绑定监听的本机ip地址和端口
$address = &#39;127.0.0.1&#39;;
$port = 81;

error_reporting(E_ALL);

//防止超时
set_time_limit(0);

//开启绝对刷送,禁止缓冲内容
ob_implicit_flush();

//创建套接字资源
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
}
//绑定套接字到端口
if (socket_bind($sock, $address, $port) === false) {
    echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}
//开始监听端口,参数5表示可以让5个连接请求在缓冲中排队
//排队的链接请求会在前一个连接断掉后才开始执行,该处缓冲排队数满五个后,后面的链接请求将直接忽略,客户端显示无法链接
//注意这个5并不是指可以并发进行5个链接,而是允许让5个后续链接进入排队
if (socket_listen($sock, 5) === false) {
    echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}

do {
    //程序运行到此处进行阻塞,就像暂停执行一样,一旦有请求进入,该函数停止阻塞,返回链接资源
    if (($client_sock = socket_accept($sock)) === false) {
        echo "socket_accept() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
        break;
    }
    echo "[client connect start]\n";
    $data = ""; //接收的数据
    $data_size = -1; //接收的数据大小
    $received_size = 0; //实际接收的数据
    $ext_name = "txt"; //默认文件扩展名

    //开始与客户端交互
    do {
        //运行到该处产生阻塞,一旦有内容则停止阻塞状态,返回内容
        if (false === ($buf = socket_read($client_sock, 2048))) {
            echo "socket_read() failed: reason: " . socket_strerror(socket_last_error($client_sock)) . "\n";
            break 2; //读取不了就返回失败,此处的2会让客户端断掉链接后停止本模拟服务器
        }
        if ($data_size === -1) {//第一次接受数据,解析通讯协议
            $arr = explode("::", $buf, 3);
            $data_size = (int)$arr[0];
            $ext_name = $arr[1];
            $data .= $arr[2];
            $received_size += strlen($data);
            continue;
        }
        $data .= $buf;
        $received_size += strlen($buf);
        if ($data_size <= $received_size) {
            if ($data_size < $received_size) {
                $data = substr($data, 0, $data_size);
            }

            echo "received:" . $received_size . "/" . "total:" . $data_size;
            $talkback = "-end-"; //发送通讯结束标志
            socket_write($client_sock, $talkback, strlen($talkback));
            file_put_contents("servertest." . $ext_name, $data);
            break 2; //关闭服务器
        }

        echo $talkback = "received:" . $received_size . "\n";
        socket_write($client_sock, $talkback, strlen($talkback));


    } while (true);
    socket_close($client_sock);

} while (true);

socket_close($sock);
?>

クライアント側プログラム:

<?php
/**
 * 本程序演示php网络编程:socket通讯 需要php开启php_sockets扩展
 * 这是一个简易的客户端程序,向服务器发送文件
 * 通讯协议约定为:文件大小::文件扩展名::有效数据
 * 通讯结束标识符为:“-end-”
 * 在命令行或浏览器中执行均可,推荐命令行,需先开启服务器端
 * 作者:云客【云游天下,作客四方】
 */

/****配置****/
$file = "yunke.jpg"; //待发送的文件
//服务器ip和端口号
$address = &#39;127.0.0.1&#39;;
$port = 81;


error_reporting(E_ALL);

// 防止超时 
set_time_limit(0);

// 开启绝对刷送,不要缓冲输出
ob_implicit_flush(true);

//创建套接字资源
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
    exit();
}
//打开到远程主机的链接
if (socket_connect($sock, $address, $port) === false) {
    echo "socket_connect() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
    exit();
}

//构造一个很大的待发送数据 大约10MB
/*
$data = "";
for ($i = 1; $i <= 10000000; $i++) {
    $data .= "data:" . $i;
}
$data = $data . $data . $data;
*/

$data = file_get_contents($file);
$data_size = strlen($data);
$arr_temp = explode(&#39;.&#39;, $file);
$ext_name = end($arr_temp);
$sock_data = $data_size . "::" . $ext_name . "::" . $data;

//发送数据给远程主机
while (true) {
    $sock_data_size = strlen($sock_data);
    $send_size = socket_write($sock, $sock_data, $sock_data_size);
    if ($send_size === false) {
        echo "send false:" . socket_strerror(socket_last_error($sock)) . "\n";
        socket_close($sock);
        echo "[client shutdown]\n";
        exit();
    }
    if ($send_size == $sock_data_size) {
        break;
    }
    $sock_data = substr($sock_data, $send_size);
}

//读返回数据
while (true) {
    if (false === ($out = socket_read($sock, 2048))) {
        echo "socket_read() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
        break 1;
    }

    echo "server: " . $out . "\n";
    if (substr($out, -5) == "-end-") { //约定结束标志
        break;
    }
}
//关闭套接字资源
socket_close($sock);
echo "[client shutdown]\nsend data:" . format($data_size);

function format($byte = 0)
{
    if ($byte > 1024 * 1024) {
        return ceil($byte / (1024 * 1024)) . "MB";
    } elseif ($byte > 1024) {
        return ceil($byte / 1024) . "KB";
    } else {
        return $byte . " Byte";
    }
}


この例は、実際のプロジェクトで通信するために、TCP ショート リンクを介してサーバーにファイルを送信する方法を示しています。モジュールはそれほど単純ではなく、さらに多くの問題を考慮する必要があります

例:

長い接続方法が必要かどうか (データは TCP リンクで複数回送受信される)、データ検証損傷の防止、および異なるシステム間のサイズ エンディアンネスの問題、カスタム通信プロトコル、パケット固着の問題、タイムアウト処理、同時アクセス、フロー制御、TCP パケットのアンパックなど

PHP ネットワークを深く理解したい場合プログラミングについては、上記のすべてを体系的に学習する必要があります。workman の実装を参照することをお勧めします

これは、ソケット通信の問題を解決するために使用できる、PHP で書かれたソケット サーバー フレームワークです。カスタムサーバーなど
workerman 公式 Web サイトのアドレスは次のとおりです: http://www.workerman.net/

以下は、サーバーの HTTP ヘッダーとブラウザーのヘッダーを表示するためのさらに 2 つのサンプル プログラムです:

次の例では、サーバーから返されたヘッダー情報を表示し、表示する必要があるサーバー アドレスを変更して、ブラウザーでスクリプトにアクセスするだけです。

<?php
error_reporting(E_ALL);

// 防止超时 
set_time_limit(0);

// 开启绝对刷送,不要缓冲输出
ob_implicit_flush(true);

$address = &#39;www.qq.com&#39;; //要查看的服务器
$port=80;

//创建套接字资源
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
    exit();
}
//打开到远程主机的链接
if (socket_connect($sock, gethostbyname($address), $port) === false) {
    echo "socket_connect() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
    exit();
}

//构造http头
$msg = "GET / HTTP/1.1 \r\n";
$msg .= "Host: {$address}\r\n";
$msg .= "Connection: Close\r\n\r\n";  
//指示服务器发回完毕就断开,不必等等其他资源的链接
//如果没有该行会,服务器会一直等待我方继续发送数据,直到超时关闭
//而我方不会再发送,这个会让下面的socket_read函数互为等待,等很久

//发送给远程主机
socket_write($sock, $msg, strlen($msg));

$str="";
while ($out = @socket_read($sock, 2048*4)) {
    $str.=$out;
}
$str=explode("\r\n\r\n", $str);
$str=$str[0];
if($str)
{
    echo "<pre class="brush:php;toolbar:false">\r\n".$str."\r\n
"; }else{     echo "nothing"; } //关闭套接字资源 socket_close($sock);

以下は、ブラウザのヘッダーを使用すると、ブラウザから送信されたセッション情報を簡単に表示できます
まずポート 80 が閉じられていることを確認してから、マシンのホスト ファイルを変更し、アクセスしたい URL をローカル 127.0.0.1 アドレスに誘導し、php を使用します。コマンド ライン モードでこのスクリプトを開始し、ブラウザを使用して設定された URL にアクセスします。プログラムを閉じる必要がある場合は、コンソールで Ctrl+C キーの組み合わせを使用してください。は次のとおりです:

<?php
error_reporting(E_ALL);

//防止超时
set_time_limit(0);

//开启绝对刷送,禁止缓冲内容
ob_implicit_flush();

$address = &#39;127.0.0.1&#39;;
$port = 80;

//创建套接字资源
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
}
//绑定套接字到端口
if (socket_bind($sock, $address, $port) === false) {
    echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}
//开始监听端口,参数5表示可以让5个连接请求在缓冲中排队
//排队的链接请求会在前一个连接断掉后才开始执行,该处缓冲排队数满五个后,后面的链接请求将显示无法链接
//注意这个5并不是指可以并发进行5个链接,而是允许让5个后续链接进入排队
if (socket_listen($sock, 5) === false) {
    echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}

do {
    //程序运行到此处进行阻塞,就像暂停执行一样,一旦有请求进入,该函数停止阻塞,返回链接资源
    //可以使用socket_set_nonblock函数设置非阻塞模式
    if (($msgsock = socket_accept($sock)) === false) {
        echo "socket_accept() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n";
        break;
    }
    
    //链接成功后在控制台显示提示
    echo "[client start ".date("Y-m-d H:i:s")."]\n\n";
    
    do {
        //运行到该处产生阻塞,一旦有内容则停止阻塞状态,返回内容
        if (false === ($buf = socket_read($msgsock, 2048*6))) {
            echo "socket_read() failed: reason: " . socket_strerror(socket_last_error($msgsock)) . "\n";
            break 2; //读取不了就返回失败,此处的2会让客户端断掉链接后停止本模拟服务器
        }
        $talkback ="HTTP/1.1 200 OK\r\n\r\n";
        $talkback .= date("Y-m-d H:i:s")."\nBrowser HTTP Headers:\n\n".$buf."\n";
        //向客户端显示该内容
        socket_write($msgsock, $talkback, strlen($talkback));
        //向服务器控制台显示该内容
        echo "$buf\n";
        break ; //中断本次与浏览器的链接
    } while (true);
    socket_close($msgsock);
} while (true);

socket_close($sock);
?>

関連する推奨事項:

Linux でソケット通信用のローカル ソース ポート番号を取得する方法

PHP ソケット サーバー 構築例とテスト例の共有

シンプルPHPでSocketを使う方法

以上がPHPでのソケット通信の詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
どのデータをPHPセッションに保存できますか?どのデータをPHPセッションに保存できますか?May 02, 2025 am 12:17 AM

phpssionscanStorestrings、numbers、arrays、andobjects.1.strings:textdatalikeusernames.2.numbers:integersorfloatsforcounters.3.arrays:listslikeshoppingcarts.4.objects:complextructuresthataresialized。

どのようにPHPセッションを開始しますか?どのようにPHPセッションを開始しますか?May 02, 2025 am 12:16 AM

tostartaphpsession、outsession_start()atthescript'sbeginning.1)placeitbe foreanyouttosetthesscookie.2)usesionsionsionsionserdatalikelogintatussorshoppingcarts.3)再生セッションインドストップレベントフィックスアタック

セッションの再生とは何ですか?また、セキュリティをどのように改善しますか?セッションの再生とは何ですか?また、セキュリティをどのように改善しますか?May 02, 2025 am 12:15 AM

セッション再生とは、新しいセッションIDを生成し、セッション固定攻撃の場合にユーザーが機密操作を実行するときに古いIDを無効にすることを指します。実装の手順には次のものが含まれます。1。感度操作を検出、2。新しいセッションIDを生成する、3。古いセッションIDを破壊し、4。ユーザー側のセッション情報を更新します。

PHPセッションを使用する際のパフォーマンスの考慮事項は何ですか?PHPセッションを使用する際のパフォーマンスの考慮事項は何ですか?May 02, 2025 am 12:11 AM

PHPセッションは、アプリケーションのパフォーマンスに大きな影響を与えます。最適化方法には以下が含まれます。1。データベースを使用してセッションデータを保存して応答速度を向上させます。 2。セッションデータの使用を削減し、必要な情報のみを保存します。 3.非ブロッキングセッションプロセッサを使用して、同時実行機能を改善します。 4.セッションの有効期限を調整して、ユーザーエクスペリエンスとサーバーの負担のバランスを取ります。 5.永続的なセッションを使用して、データの読み取り時間と書き込み時間を減らします。

PHPセッションはCookieとどのように異なりますか?PHPセッションはCookieとどのように異なりますか?May 02, 2025 am 12:03 AM

phpsesionsareserver-side、whilecookiesareclient-side.1)Sessionsionsionsoredataontheserver、aremoresecure.2)cookiesstoredataontheclient、cookiestoresecure、andlimitedinsizeisize.sesionsionsionivationivationivationivationivationivationivationivate

PHPはユーザーのセッションをどのように識別しますか?PHPはユーザーのセッションをどのように識別しますか?May 01, 2025 am 12:23 AM

phpidentifiesauser'ssessionsingsinssessionCookiesIds.1)whensession_start()iscalled、phpgeneratesauniquesidstoredsored incoookienadphpsessidontheuser'sbrowser.2)thisidallowsphptortorieSessiondatadata fromthata

PHPセッションを保護するためのベストプラクティスは何ですか?PHPセッションを保護するためのベストプラクティスは何ですか?May 01, 2025 am 12:22 AM

PHPセッションのセキュリティは、次の測定を通じて達成できます。1。session_regenerate_id()を使用して、ユーザーがログインまたは重要な操作である場合にセッションIDを再生します。 2. HTTPSプロトコルを介して送信セッションIDを暗号化します。 3。Session_Save_Path()を使用して、セッションデータを保存し、権限を正しく設定するためのSecure Directoryを指定します。

PHPセッションファイルはデフォルトで保存されていますか?PHPセッションファイルはデフォルトで保存されていますか?May 01, 2025 am 12:15 AM

phpsessionFilesToredInthededirectoryspecifiedBysession.save_path、通常/tmponunix-likesystemsorc:\ windows \ temponwindows.tocustomizethis:1)uesession_save_path()tosetaCustomdirectory、ensuringit'swritadistradistradistradistradistra

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

AtomエディタMac版ダウンロード

AtomエディタMac版ダウンロード

最も人気のあるオープンソースエディター