Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
不使用数据库或文件的php网络聊天_Php_Design Patterns_Web Applications - Fatal编程技术网

不使用数据库或文件的php网络聊天

不使用数据库或文件的php网络聊天,php,design-patterns,web-applications,Php,Design Patterns,Web Applications,我正在尝试使用PHP实现一个实时聊天应用程序。是否可以不使用数据库或文件等持久数据存储来实现这一点。基本上我需要的是一个用PHP编写的中介 接受来自客户端浏览器的消息 将消息广播到其他客户端 忘记留言 如果您只需要使用PHP,那么您可以将聊天消息存储在会话变量中,会话可以像对象一样,存储大量信息。 若您可以使用jQuery,那个么您可以在消息发送后将段落附加到div,但若站点被刷新,消息就会消失。 或者组合,在会话中存储消息,并使用jQuery和ajax进行更新。简而言之,您不能。 当前的HTT

我正在尝试使用PHP实现一个实时聊天应用程序。是否可以不使用数据库或文件等持久数据存储来实现这一点。基本上我需要的是一个用PHP编写的中介

  • 接受来自客户端浏览器的消息
  • 将消息广播到其他客户端
  • 忘记留言

  • 如果您只需要使用PHP,那么您可以将聊天消息存储在会话变量中,会话可以像对象一样,存储大量信息。 若您可以使用jQuery,那个么您可以在消息发送后将段落附加到div,但若站点被刷新,消息就会消失。
    或者组合,在会话中存储消息,并使用jQuery和ajax进行更新。

    简而言之,您不能。 当前的HTTP/HTML实现不支持
    pushstate
    ,因此聊天应用程序的算法应遵循:

  • A:发送消息
  • B、 C,D:在发送新消息时执行此操作,以获取此消息
  • 因此,接收者总是必须发出新的请求,并检查是否发送了新的消息。(AJAX调用或类似的东西) 因此,发送事件和接收事件之间总是存在延迟

    • 这意味着数据必须保存在全局中,如数据库或文件系统
    看看:
    您需要使用某种存储作为缓冲区。不使用文件或数据库(也使用文件)是不可取的。您可以尝试使用php函数,但我不知道任何有效的解决方案,因此您必须从头开始使用。

    尝试查看套接字库,就像它们允许即时传输消息,并且比TCP更快,而且是实时的一样。他们的基础设施允许在A点和B点之间即时发送数据,而无需先将数据存储在任何位置(尽管您仍然可以选择)。
    这里有一个

    你应该看看html5的网络套接字。它使用双向连接,所以您不需要任何数据库或文件。任何发送到服务器的聊天信息都将直接发送到其他用户的浏览器,而无需任何Ajax调用。但您还需要设置web套接字服务器

    <?php
    
    // Set time limit to indefinite execution
    
    set_time_limit (0);
    
    // Set the ip and port we will listen on
    
    $address = '192.168.0.100';
    
    $port = 9000;
    
    $max_clients = 10;
    
    // Array that will hold client information
    
    $clients = Array();
    
    // Create a TCP Stream socket
    
    $sock = socket_create(AF_INET, SOCK_STREAM, 0);
    
    // Bind the socket to an address/port
    
    socket_bind($sock, $address, $port) or die('Could not bind to address');
    
    // Start listening for connections
    
    socket_listen($sock);
    
    // Loop continuously
    
    while (true) {
    
        // Setup clients listen socket for reading
    
        $read[0] = $sock;
    
        for ($i = 0; $i < $max_clients; $i++)
    
        {
    
            if ($client[$i]['sock']  != null)
    
                $read[$i + 1] = $client[$i]['sock'] ;
    
        }
    
        // Set up a blocking call to socket_select()
    
        $ready = socket_select($read,null,null,null);
    
        /* if a new connection is being made add it to the client array */
    
        if (in_array($sock, $read)) {
    
            for ($i = 0; $i < $max_clients; $i++)
    
            {
    
                if ($client[$i]['sock'] == null) {
    
                    $client[$i]['sock'] = socket_accept($sock);
    
                    break;
    
                }
    
                elseif ($i == $max_clients - 1)
    
                    print ("too many clients")
    
            }
    
            if (--$ready <= 0)
    
                continue;
    
        } // end if in_array
    
    
    
        // If a client is trying to write - handle it now
    
        for ($i = 0; $i < $max_clients; $i++) // for each client
    
        {
    
            if (in_array($client[$i]['sock'] , $read))
    
            {
    
                $input = socket_read($client[$i]['sock'] , 1024);
    
                if ($input == null) {
    
                    // Zero length string meaning disconnected
    
                    unset($client[$i]);
    
                }
    
                $n = trim($input);
    
                if ($input == 'exit') {
    
                    // requested disconnect
    
                    socket_close($client[$i]['sock']);
    
                } elseif ($input) {
    
                    // strip white spaces and write back to user
    
                    $output = ereg_replace("[ \t\n\r]","",$input).chr(0);
    
                    socket_write($client[$i]['sock'],$output);
    
                }
    
            } else {
    
                // Close the socket
    
                socket_close($client[$i]['sock']);
    
                unset($client[$i]);
    
            }
    
        }
    
    } // end while
    
    // Close the master sockets
    
    socket_close($sock);
    
    ?>
    

    Web套接字也用于许多实时应用程序中。我很快计划写一篇关于这方面的完整教程。我会通知您。

    您将要使用
    套接字。本文将详细介绍您想要做的事情:

    有没有可能不使用像这样的持久数据存储 数据库还是文件

    这是可能的,但您不应该使用。基于数据库或文件不会减慢聊天速度。它将为您的聊天应用程序提供额外的安全性。您可以使用ajaxsockets进行基于web的聊天,而无需持久数据

    您应该看到以下帖子:


  • 实现这一点的一个解决方案是编写一个PHP套接字服务器

    <?php
    
    // Set time limit to indefinite execution
    
    set_time_limit (0);
    
    // Set the ip and port we will listen on
    
    $address = '192.168.0.100';
    
    $port = 9000;
    
    $max_clients = 10;
    
    // Array that will hold client information
    
    $clients = Array();
    
    // Create a TCP Stream socket
    
    $sock = socket_create(AF_INET, SOCK_STREAM, 0);
    
    // Bind the socket to an address/port
    
    socket_bind($sock, $address, $port) or die('Could not bind to address');
    
    // Start listening for connections
    
    socket_listen($sock);
    
    // Loop continuously
    
    while (true) {
    
        // Setup clients listen socket for reading
    
        $read[0] = $sock;
    
        for ($i = 0; $i < $max_clients; $i++)
    
        {
    
            if ($client[$i]['sock']  != null)
    
                $read[$i + 1] = $client[$i]['sock'] ;
    
        }
    
        // Set up a blocking call to socket_select()
    
        $ready = socket_select($read,null,null,null);
    
        /* if a new connection is being made add it to the client array */
    
        if (in_array($sock, $read)) {
    
            for ($i = 0; $i < $max_clients; $i++)
    
            {
    
                if ($client[$i]['sock'] == null) {
    
                    $client[$i]['sock'] = socket_accept($sock);
    
                    break;
    
                }
    
                elseif ($i == $max_clients - 1)
    
                    print ("too many clients")
    
            }
    
            if (--$ready <= 0)
    
                continue;
    
        } // end if in_array
    
    
    
        // If a client is trying to write - handle it now
    
        for ($i = 0; $i < $max_clients; $i++) // for each client
    
        {
    
            if (in_array($client[$i]['sock'] , $read))
    
            {
    
                $input = socket_read($client[$i]['sock'] , 1024);
    
                if ($input == null) {
    
                    // Zero length string meaning disconnected
    
                    unset($client[$i]);
    
                }
    
                $n = trim($input);
    
                if ($input == 'exit') {
    
                    // requested disconnect
    
                    socket_close($client[$i]['sock']);
    
                } elseif ($input) {
    
                    // strip white spaces and write back to user
    
                    $output = ereg_replace("[ \t\n\r]","",$input).chr(0);
    
                    socket_write($client[$i]['sock'],$output);
    
                }
    
            } else {
    
                // Close the socket
    
                socket_close($client[$i]['sock']);
    
                unset($client[$i]);
    
            }
    
        }
    
    } // end while
    
    // Close the master sockets
    
    socket_close($sock);
    
    ?>
    
    
    
    您可以通过命令行运行它来执行此操作,并且必须始终运行PHP客户端才能连接到它。然后,您可以编写一个连接到套接字的PHP客户端

    <?php
    $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
    if (!$fp) {
        echo "$errstr ($errno)<br />\n";
    } else {
        $out = "GET / HTTP/1.1\r\n";
        $out .= "Host: www.example.com\r\n";
        $out .= "Connection: Close\r\n\r\n";
        fwrite($fp, $out);
        while (!feof($fp)) {
            echo fgets($fp, 128);
        }
        fclose($fp);
    }
    ?>
    
    
    
    您必须使用某种类型的ajax来调用jQuery,并将消息发布到此PHP客户端


    http://php.net/manual/en/function.fsockopen.php

    我只是尝试了一些我以前从未做过的事情来回答这个问题。似乎有效,但我只测试了一次。我没有使用套接字,而是想到了使用共享会话变量。基本上,我强制Session_id为相同的值,而不管用户是谁,因此它们都共享相同的数据。从快速测试来看,它似乎有效。以下是我所做的:

    session_id('12345');
    session_start();
    $session_id = session_id();
    $_SESSION['test'] = $_SESSION['test'] + 1;
    echo "session: {$session_id} test: {$_SESSION['test']} <br />";
    
    session_id('12345');
    会话_start();
    $session_id=session_id();
    $_会话['test']=$_会话['test']+1;
    echo“session:{$session_id}test:{$_session['test']}
    ”;
    所以我的想法是,您可以简单地将聊天信息存储在会话变量中,并强制每个人使用共享会话,而不管他们是谁。然后,您可以简单地使用ajax不断地重新加载当前会话变量,并在添加消息时使用ajax编辑会话变量。此外,您可能希望将会话设置为永不过期或具有很长的maxlifetime


    正如我所说的,我只是花了几分钟的时间来研究它是否有效。

    PHP不适合您的要求(在apache PHP、fastcgi等正常设置中),因为PHP脚本对于每个请求都从上到下执行,并且在不使用外部服务或数据库/文件的情况下无法在请求之间保持任何状态(例如,除此之外,但它不用于实现聊天,也不会扩展到多个服务器)

    您肯定应该看看Node.js,尤其是Node.js模块Socket.IO(一个Websocket库)。这是难以置信的易于使用和岩石。IO还可以通过可选的redis后端扩展到多个聊天服务器,这意味着更容易扩展


    顺便说一下,尝试使用带有静态会话id的
    $\u SESSION
    作为通信通道不是一个解决方案,因为PHP将会话数据保存到文件中。

    最好使用node.js服务器。WebSocket现在不再是跨浏览器的了(除了node.js的socket.io,它工作得非常完美)

    当我试图解决同样的问题时,我选择了Nginx。我之所以选择这种方式,是因为我必须支持较旧的浏览器(通常不支持WebSockets),并且没有信心在TCP代理之后设置合适的解决方案

    工作流程如下所示:

  • 客户端通过长轮询连接到我的
    /subscriber
    位置,该位置对所有人开放
  • /publisher
    位置仅接受来自我自己服务器的连接
  • 当客户机订阅和交谈时,它基本上只是要求一个PHP脚本来处理什么