socket 发送数据 瓶颈_PHP利用socket扩展实现聊天服务

socket聊天服务原理

3947495bac8518b1d9077490d5332f77.png

PHP有两个socket的扩展 sockets和streamssockets
socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
socket_write
socket_read
socket_close
客户端
socket_connect($socket, $address, $service_port);
服务端
socket_bind($sock, $address, $port)
socket_listen($sock)
socket_acceptStreams
客户端
stream_socket_client
fwrite
fread
fclose($fp);
服务端
stream_socket_server
stream_set_blocking
stream_select
stream_socket_accept conn
stream_socket_recvfrom
stream_socket_sendto
stream_socket_shutdown

课后练习
使用sockets和streams扩展实现客户端跟服务端的功能。

服务端代码 客服端可使用udp&tcp测试工具

<?php
 
class SocketService
{
    public $host="tcp://0.0.0.0:8000";
    private $address;
    private $port;
    private $_sockets;
    public $clients;
    public $maxid=1000;
    public function __construct($address = '', $port='')
    {
            if(!empty($address)){
                $this->address = $address;
            }
            if(!empty($port)) {
                $this->port = $port;
            }
    }
     
    public function onConnect($client_id){
        echo  "Client client_id:{$client_id}   n";
          
    }
     
    public function onMessage($client_id,$msg){
        //发给所有的
        foreach($this->clients as $kk=>$cc){
            if($kk>0){
                $this->send($cc, $msg);
            }                              
        }  
    }
     
    public function onClose($client_id){
        echo "$client_id close n";
    }
     
    public function service(){
        //获取tcp协议号码。
        $tcp = getprotobyname("tcp");
        $sock = stream_socket_server($this->host, $errno, $errstr);;
         
        if(!$sock)
        {
            throw new Exception("failed to create socket: ".socket_strerror($sock)."n");
        }
        stream_set_blocking($sock,0);
        $this->_sockets = $sock;
         echo "listen on $this->address $this->host ... n";
    }
  
    public function run(){
        $this->service();
        $this->clients[] = $this->_sockets;
        while (true){
            $changes = $this->clients;
            //$write = NULL;
            //$except = NULL;
            stream_select($changes,  $write,  $except, NULL);
            foreach ($changes as $key => $_sock){
                if($this->_sockets == $_sock){ //判断是不是新接入的socket
                    if(($newClient = stream_socket_accept($_sock))  === false){
                        unset($this->clients[$key]);
                        continue;
                    }
                    $line = trim(stream_socket_recvfrom($newClient, 1024));
                      
                    $this->maxid++;
                    $this->clients[$this->maxid] = $newClient;
                    $this->onConnect($this->maxid);
                } else {
                    $msg=@stream_socket_recvfrom($_sock,  2048);
                    if(!$msg){
                        stream_socket_shutdown($this->clients[$key],STREAM_SHUT_RDWR);
                        unset($this->clients[$key]);
                        $this->onClose($key);
                    }else{
                        $msg=$this->decode($msg);
                        $this->onMessage($key,$msg);
                    }
                     
                     
                }
            }
        }
    }
  
     
     
     
    /**
     * 发送数据
     * @param $newClinet 新接入的socket
     * @param $msg   要发送的数据
     * @return int|string
     */
    public function send($newClinet, $msg){
        $msg=$this->encode($msg);
        if($msg){
            stream_socket_sendto($newClinet, $msg);
        }
         
    }
     
    public function encode($msg){
          return $msg . "n";
    }
    public function decode($msg){
        return rtrim($msg, "rn");
    }
  
    /**
     * 关闭socket
     */
    public function close(){
        return socket_close($this->_sockets);
    }
}
  
$sock = new SocketService('127.0.0.1','9000');
$sock->run();

以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要戳这里PHP进阶架构师>>>视频、面试文档免费获取

或 者关注我每天分享技术文章

PHP架构师之路​www.zhihu.com
ce5b01915aac721063ed60edab11a084.png
作者:雷日锦的博客
原理:https://www.cnblogs.com/lrjxgl/p/11123923.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值