为了账号安全,请及时绑定邮箱和手机立即绑定

如何在PHP中创建websockets服务器

/ 猿问

如何在PHP中创建websockets服务器

侃侃无极 2019-09-19 10:31:15

是否有任何教程或指南显示如何在PHP中编写一个简单的websockets服务器?我试过在谷歌上寻找它,但我找不到很多。我发现phpwebsockets但它现在已经过时,不支持最新的协议。我自己尝试更新它,但似乎没有用。


#!/php -q

<?php  /*  >php -q server.php  */


error_reporting(E_ALL);

set_time_limit(0);

ob_implicit_flush();


$master  = WebSocket("localhost",12345);

$sockets = array($master);

$users   = array();

$debug   = false;


while(true){

  $changed = $sockets;

  socket_select($changed,$write=NULL,$except=NULL,NULL);

  foreach($changed as $socket){

    if($socket==$master){

      $client=socket_accept($master);

      if($client<0){ console("socket_accept() failed"); continue; }

      else{ connect($client); }

    }

    else{

      $bytes = @socket_recv($socket,$buffer,2048,0);

      if($bytes==0){ disconnect($socket); }

      else{

        $user = getuserbysocket($socket);

        if(!$user->handshake){ dohandshake($user,$buffer); }

        else{ process($user,$buffer); }

      }

    }

  }

}


//---------------------------------------------------------------

function process($user,$msg){

  $action = unwrap($msg);

  say("< ".$action);

  switch($action){

    case "hello" : send($user->socket,"hello human");                       break;

    case "hi"    : send($user->socket,"zup human");                         break;

    case "name"  : send($user->socket,"my name is Multivac, silly I know"); break;

    case "age"   : send($user->socket,"I am older than time itself");       break;

    case "date"  : send($user->socket,"today is ".date("Y.m.d"));           break;

    case "time"  : send($user->socket,"server time is ".date("H:i:s"));     break;

    case "thanks": send($user->socket,"you're welcome");                    break;

    case "bye"   : send($user->socket,"bye");                               break;

    default      : send($user->socket,$action." not understood");           break;

  }

}


function send($client,$msg){

  say("> ".$msg);

  $msg = wrap($msg);

  socket_write($client,$msg,strlen($msg));

}


如果的代码有什么问题你可以帮我解决吗?Firefox中的Concole说Firefox can't establish a connection to the server at ws://localhost:12345/.


查看完整描述

3 回答

?
慕娘9325324

我和你最近在同一条船上,这就是我所做的:

1)我使用phpwebsockets代码作为如何构造服务器端代码的参考。(您似乎已经这样做了,正如您所指出的,代码实际上并不是出于各种原因。)

2)我使用PHP.net来读取有关phpwebsockets代码中使用的每个套接字函数的详细信息。通过这样做,我终于能够理解整个系统在概念上如何运作。这是一个相当大的障碍。

3)我阅读了实际的WebSocket草案(请对其进行网络搜索,因为我不能在每个帖子上发布两个以上的链接)。在它最终开始陷入困境之前,我不得不多次阅读这篇文章。你可能不得不在整个过程中一次又一次地回到这个文档,因为它是一个确定的,最新的最终资源有关WebSocket API的信息。

4)我根据#3草案中的说明编写了正确的握手程序。这不是太糟糕。

5)握手后我一直收到一堆从客户端发送到服务器的乱码文本,直到我意识到数据已被编码并且必须被取消屏蔽,我才弄清楚为什么。以下链接对我有很大帮助:http://srchea.com/blog/2011/12/build-a-real-time-application-using-html5-websockets/

请注意,此链接提供的代码存在许多问题,如果不进行进一步修改将无法正常运行。

6)然后我遇到了以下SO线程,它清楚地解释了如何正确编码和解码来回发送的消息:如何在服务器端发送和接收WebSocket消息?

这个链接非常有用。我建议在查看WebSocket草案时查阅它。这将有助于更好地理解草案的内容。

7)我几乎已经完成了这一点,但是我使用WebSocket制作的WebRTC应用程序存在一些问题,所以我最终在SO上提出了自己的问题,我最终解决了这个问题。要参考问题和答案,请在网上搜索“在WebRTC候选人信息结束时这些数据是什么?” (不带引号)。

8)此时,我几乎都在努力工作。我只需要添加一些额外的逻辑来处理连接的关闭,我就完成了。

这个过程总共花了我两个星期的时间。好消息是我现在非常了解WebSocket,并且我能够从头开始制作自己的客户端和服务器脚本,效果很好。希望所有这些信息的高潮将为您提供足够的指导和信息来编写您自己的WebSocket PHP脚本。祝好运!

编辑:这个编辑是在我的原始答案之后的几年,虽然我仍然有一个有效的解决方案,但它还没有真正准备好分享。幸运的是,GitHub上的其他人拥有几乎相同的代码(但更清晰),所以我建议使用以下代码来实现有效的PHP WebSocket解决方案:https:
//github.com/ghedipunk/PHP-Websockets/blob/master/ websockets.php

编辑#2:虽然我仍然喜欢将PHP用于许多与服务器端相关的事情,但我不得不承认我最近对Node.js做了很多热情,主要原因是因为它的设计更好开始处理WebSocket而不是PHP(或任何其他服务器端语言)。因此,我最近发现,在您的服务器上设置Apache / PHP和Node.js并使用Node.js运行WebSocket服务器和Apache / PHP用于其他所有事情要容易得多。如果您在共享托管环境中无法安装/使用Node.js进行WebSocket,您可以使用像Heroku这样的免费服务来设置Node.js WebSocket服务器并进行跨域从您的服务器请求它。


查看完整回答
反对 回复 2019-09-19
?
暮色呼如

据我所知,Ratchet是目前最好的PHP WebSocket解决方案。而且由于它是开源的,你可以看到作者是如何使用PHP构建这个WebSocket解决方案的。


查看完整回答
反对 回复 2019-09-19
?
慕后森

为什么不使用套接字http://uk1.php.net/manual/en/book.sockets.php?它有很好的文档记录(不仅在PHP上下文中)并且有很好的例子http://uk1.php.net/manual/en/sockets.examples.php


查看完整回答
反对 回复 2019-09-19

添加回答

回复

举报

0/150
提交
取消
意见反馈 邀请有奖 帮助中心 APP下载
官方微信