私聊(PHP 實現)

灰色v碰觸發表於2019-02-16

服務端


$url = `tcp://0.0.0.0:9160`;

$stream = stream_socket_server($url , $errno , $errstr);

// 設定阻塞模式
stream_set_blocking($stream , false);

$client_list = [];

$resource_list = [];

$resource_list[] = $stream;

$find= function($client) use(&$client_list){
   foreach ($client_list as $k => $v)
   {
       if ($v[`resource`] === $client) {
           return $k;
       }
   }

   echo `在現有資源列表中找不到給定資源對應的索引` . PHP_EOL;

   return false;
};

$find_client = function($username) use(&$client_list) {
    foreach ($client_list as $v)
    {
        if ($v[`username`] === $username) {
            return $v[`resource`];
        }
    }

    echo `在現有資源列表中找不到給定使用者對應的客戶端資源` . PHP_EOL;

    return false;
};

while (true)
{
    $read = $resource_list;
    $write = $resource_list;
    $except = [];
    $wait_s = 0;
    $wait_us = 0;

    stream_select($read , $write , $except , $wait_s , $wati_us);

    foreach ($read as $v)
    {
        if ($v === $stream) {
            // 監聽客戶端連線
            $client = stream_socket_accept($v);

            if (is_resource($client)) {
                $resource_list[] = $client;

                $client_list[] = [
                    `username` => null ,
                    `resource` => $client
                ];
            }
        } else {
            $index = $find($v);
            $user  = $client_list[$index];

            // 監聽客戶端訊息
            $msg = fread($v , 65535);

            if (!empty($msg)) {
                if (!is_null($user) && is_null($user[`username`]) && preg_match(`/username:(w+)/` , $msg , $matches) === 1) {
                    $client_list[$index][`username`] = $matches[1];
                } else {
                    $msg = unserialize($msg);

                    $client = $find_client($msg[`to`]);

                    if ($client !== false) {
                        fwrite($client , serialize($msg));
                    } else {
                        echo "來自客戶端的訊息:from:{$msg[`from`]};to:{$msg[`to`]};msg:{$msg[`msg`]}
";
                    }
                }
            }
        }
    }

    usleep(100 * 1000);
}

客戶端 A(接受客戶端 B 發來的訊息)

<?php
/**
 * Created by PhpStorm.
 * User: grayvtouch
 * Date: 17-10-23
 * Time: 下午3:30
 */

$url = `tcp://127.0.0.1:9160`;

$client = stream_socket_client($url , $strno , $strstr);

$duration = 20;
$s_time = time();

stream_set_blocking($client , false);

$username = `chenxuelong`;

$send = [
    `from` => $username ,
    `to` => `yueshu` ,
    `msg` => `hello girl`
];

$is_flag = false;

while (true)
{
    $e_time = time();

    if ($e_time - $s_time > $duration) {
        echo "20s 時間到" . PHP_EOL;
        break;
    }

    if (!$is_flag) {
        fwrite($client , `username:` . $username);

        $is_flag = true;
    } else {
        // $sends = serialize($send);

        // fwrite($client , $sends);
    }

    $msg = fread($client , 65535);

    if (!empty($msg)) {
        $msg = unserialize($msg);

        echo "來自{$msg[`from`]}的訊息:{$msg[`msg`]}
";
    }

    usleep(10 * 1000);
}

客戶端 B(傳送訊息給客戶端 A)

<?php
/**
 * Created by PhpStorm.
 * User: grayvtouch
 * Date: 17-10-23
 * Time: 下午3:30
 */

$url = `tcp://127.0.0.1:9160`;

$client = stream_socket_client($url , $strno , $strstr);

$duration = 20;
$s_time = time();

stream_set_blocking($client , false);

$username = `yueshu`;

$msg = [
    `from` => $username ,
    `to` => `chenxuelong` ,
    `msg` => `hello boy`
];

$is_flag = false;

while (true)
{
    $e_time = time();

    if ($e_time - $s_time > $duration) {
        echo "20s 時間到" . PHP_EOL;
        break;
    }

    if (!$is_flag) {
        fwrite($client , `username:` . $username);

        $is_flag = true;
    } else {
        $send = serialize($msg);

        fwrite($client , $send);
    }

    /*
    $msg = fread($client , 65535);

    if (!empty($msg)) {
        $msg = unserialize($msg);

        echo "來自{$msg[`from`]}的訊息:{$msg[`msg`]}
";
    }
    */

    sleep(1);
}

相關文章