私聊(PHP 实现)

服务端


$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']}\n";
                    }
                }
            }
        }
    }

    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']}\n";
    }

    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']}\n";
    }
    */

    sleep(1);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值