WebSocket [编辑本页]

swoole-1.7.9 增加了内置的websocket服务器支持,通过几行PHP代码就可以写出一个异步非阻塞多进程的WebSocket服务器。

$server = new swoole_websocket_server("0.0.0.0", 9501);

$server->on('open', function (swoole_websocket_server $server, $request) {
    echo "server: handshake success with fd{$request->fd}\n";
});

$server->on('message', function (swoole_websocket_server $server, $frame) {
    echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
    $server->push($frame->fd, "this is server");
});

$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});

$server->start();

onRequest回调

swoole_websocket_server 继承自 swoole_http_server

  • 设置了onRequest回调,websocket服务器也可以同时作为http服务器
  • 未设置onRequest回调,websocket服务器收到http请求后会返回http 400错误页面

客户端

  • Chrome/Firefox/高版本IE/Safari等浏览器内置了JS语言的WebSocket客户端
  • 微信小程序开发框架内置的WebSocket客户端
  • 异步的PHP程序中可以使用Swoole\Http\Client作为WebSocket客户端
  • apache/php-fpm或其他同步阻塞的PHP程序中可以使用swoole/framework提供的同步WebSocket客户端
  • 非WebSocket客户端不能与WebSocket服务器通信

  • 松松饭

    1.7.14版本下, on和message的参数都报错了,有新版的手册吗?

  • 松松饭

    看了下源码,1.7.14版 "on"的参数是 :function (swoole_websocket_server $server, swoole_http_request $req) "message"的参数是:function (swoole_websocket_server $server, swoole_websocket_frame $frame)

  • 张良晖

    message和close事件都是server上的?不应该是connection上的事件吗

  • nfer

    能否也对应的开发一个 swoole_websocket_client

  • 霸气千秋

    源码的 example/websocket 目录下有个 php 实现的 WebSocketClient

  • 刘朱石强

    websocket 下 $server->set(array('worker_num' => 1)); 不管用。

  • 刘朱石强

    搞错了,$server->set(array('worker_num' => 1)); 可以正常使用。

  • Just_Fee1ing

    PHP Fatal error: swoole_server::on(): Unknown event types[message] 就我一个人报这个error? swoole版本1.7.17

  • Just_Fee1ing

    饿。。知道咋回事了。。

  • guoerwei

    Argument 2 passed to {closure}() must be an instance of swoole_http_request, integer given on.('open')里面第二个参数传进来的是一个整数…

  • guoerwei

    同样on('message')的时候,$frame传进来也是一个整数int(1)…

  • guoerwei

    哦…之前是1.7.11,现在是1.7.17,正常了

  • 小马哥

    我怎么就 new swoole_server("127.0.0.1", 9501); 能连接上, new swoole_http_server("127.0.0.1", 9501); 和 new swoole_websocket_server("0.0.0.0", 9501); 都链接不上 ,版本 1.7.19

  • 爱好者

    有没有函数判断客户端还正在链接呢

  • 阿强

    今天试难成功,连上了,按照github上的例子连了一下,服务器端的信息: PHP Notice: Undefined property: swoole_http_request::$get in /var/www/html/ws.php on line 5 int(1) NULL array(9) { ["request_method"]=> string(3) "GET" ["request_uri"]=> string(1) "/" ["path_info"]=> string(1) "/" ["request_time"]=> int(1447532507) ["server_port"]=> int(9502) ["remote_port"]=> int(53188) ["remote_addr"]=> string(13) "192.168.1.102" ["server_protocol"]=> string(8) "HTTP/1.1" ["server_software"]=> string(18) "swoole-http-server" }

  • xcwenn@qq.com

    android 哪个websocket lib 合适?!

  • 他的流年

    您好,请问我如何在服务器主动关闭一个连接呢?

  • 他的流年

    不好意思,问题已解决。是我看得不够清楚,由继承关系直接调用close函数就可以关闭连接

  • seven

    我也想知道 怎么主动关闭一个连接 没看到你的什么意思 求大大给个代码案例看呢

  • 孙佳兵

    为什么我在客户端的js方法 socket.onopen能够相应,socket.opmessage响应不了?

  • jimmy

    swoole_websocket_server 的工作进程数怎么控制?

  • heice

    在吗?请问这个要怎么实现? 接收到redis的数据又把数据从websocket传出去 var app = require('http').createServer(handler); var io = require('socket.io')(app);

    var Redis = require('ioredis'); var redis = new Redis('6379','127.0.0.1');

    app.listen(6001, function() { console.log('Server is running!'); });

    function handler(req, res) { res.writeHead(200); res.end(''); }

    io.on('connection', function(socket) { // console.log('connected'); });

    redis.psubscribe('*', function(err, count) { // console.log('count'); });

    redis.on('pmessage', function(subscribed, channel, message) { console.log(subscribed); console.log(channel); console.log(message); message = JSON.parse(message); io.emit(channel + ':' + message.event, message.data); });

  • 骑驴泡美妞

    您好,可以问下是怎么解决的么?

  • 别怕

    页面直接写上这段js就行吗?为什么我在命令行运行之后 打开有这段js的页面什么也不显示?如果直接输入地址加上端口号的就出来一个websocket已经通电的话

  • 谭少民-倬余

    请问如何分房间?

  • 猫爸爸

    求助大大们,websocket 在IE11下上传超过50M的文件时提示,报文过长然后自动断开了,这是BUG还是我方式不对?chrome没有相关的问题,前端使用FileReader.readAsArrayBuffer()读取文件 WARNING swProtocol_recv_check_length: package is too big, remote_addr=192.168.5.1:52151, length=50772334. [/documents/bin/swoole-src-master/src/network/Port.c:340@swPort_onRead_check_length]Close Event.FD=32|From=0 client 1 quit

  • 谭少民-倬余

    请问单个服务端最大支持多少链接数?

  • 张三丰

    参照max_connection配置

  • 张三丰

    分房间应该是自己业务层去自己实现

  • d7788250

    Swoole\Http\Client作为WebSocket客户端有例程吗?

  • 快捷方式

    server: handshake success with fd1 receive from 1:hello yii,opcode:1,fin:1 client 1 closed [2017-04-20 15:14:42 #11571.2] WARNING swReactorThread_send: connection#18 is closed by client. server: handshake success with fd2 receive from 2:hello yii,opcode:1,fin:1 client 2 closed [2017-04-20 15:14:45 #11571.2] WARNING swReactorThread_send: connection#18 is closed by client. server: handshake success with fd3 receive from 3:hello yii,opcode:1,fin:1 client 3 closed [2017-04-20 15:14:48 #11571.2] WARNING swReactorThread_send: connection#18 is closed by client. server: handshake success with fd4 receive from 4:hello yii,opcode:1,fin:1 client 4 closed [2017-04-20 15:14:51 #11571.2] WARNING swReactorThread_send: connection#18 is closed by client. server: handshake success with fd5 receive from 5:hello yii,opcode:1,fin:1 client 5 closed [2017-04-20 15:14:53 #11571.2] WARNING swReactorThread_send: connection#18 is closed by client.

  • 快捷方式

    $webSocketClient = new \app\exts\WebSocketClient('121.11.71.33', 8988);

        $webSocketClient->connect();
    
        $webSocketClient->send('hello yii');
    
        $webSocketClient->close();
    

  • 快捷方式

    $server = new \swoole_websocket_server("121.11.71.33", 8988);

        $server->on('open', function (\swoole_websocket_server $server, $request) {
            echo "server: handshake success with fd{$request->fd}\n";
        });
    
        $server->on('message', function (\swoole_websocket_server $server, $frame) {
            echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
            $server->push($frame->fd, "this is server");
        });
    
        $server->on('close', function ($ser, $fd) {
            echo "client {$fd} closed\n";
        });
    
        $server->start();
    

  • 快捷方式

    为什么close之后还有warning,这是哪里给clien发送信息了吗

  • 王子

    请问如何使用websocket做分布式转发服务端?貌似swoole的websocket只有server,没有client

  • CodingMan

    failed: Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT 两台服务器,一台能成功,另外一台运行了websocket的例子。浏览器端js连不上报这个错,谁碰到过啊

  • wHiLe(1)追;

            if(!($roomMember = RoomMembers::find($userid)))
            {
                return false;
            }
    
            $roomid = $roomMember->roomid;
    
            //座位找到了,但未找到对应的房间
            if(!($room = Room::find($roomid)))
            {
                $roomMember->delete();
                return false;
            }
    

    如果所示经过几轮异步数据请求后,RoomMembers所获取的对象是仍然是该对象本身,但是属性却变成了Room的属性了。数据在底层发生了混乱。 虽然这是业务逻辑的代码,本应该跟Swoole没有关系。但是同样用Swoole的Socket的时候,没有这个问题(其他代码完全一样,仅接入层不一样)。我是先写好Socket版本测试没问题后,打算接入小程序才尝试的Websocket。

    另外测试方面,我是自己写的机器人,Websocket几乎每次都是跑2~3轮就出现数据混乱。而Socket版本跑几个小时,没有任何问题。由于能力有限,只能根据现象猜测是Swoole的Websocket有问题。还请抽空帮忙看一下,急等接入小程序版本的游戏。多谢!

  • wHiLe(1)追;

    继续楼上:把worker_num 设置为1后,没有这个问题。但是这样不合理啊。 Socket的时候worker_num设置为4,也是正常工作的。 是我哪里设置有问题吗?

  • wHiLe(1)追;

    继续楼上:经过进一步测试,是在采用websocket并且worker_num>1并且并发请求同一个function资源的时候,会发生这个情况。 也已经在码云上面提交BUG了。

  • 初学者想学一下swoole,希望有人给予解答: 是不是一个类似网络棋牌游戏大厅这种网页游戏,服务端就可以用swoole_websocket_server? 客户端是用http_client还是直接js的websocket? 有没有大神给解释下swoole各服务器和客户端到底怎么用?以游戏大厅为例说一下整体系统架构。

  • phper

    请问一下,IE低版本浏览器怎样用flash去连接Websocket