关于send发送长消息体后续send无效的问题。

cfz87862529

我在测试workerman时下了如下的简单测试代码:

public function workerOnMessage($connection, $data)
    {
        $ip = $connection->getRemoteIp();
        if ($ip == '127.0.0.1') {
            $data = str_replace('\\"', '"', str_replace('\r\n', '', $data));
            $data = ltrim($data, '"');
            $data = rtrim($data, '"');
        }
        if ($data == '@') { //判断数据是不是@,作为心跳包
            $connection->send('@');
        }

        if($data == '1'){
            $str1 = "1111111111111111111111111111111111111111111111111111111111111111111";
            for($i = 0; $i < 10000000; $i++){
                $str1 .= '*';
            }
            $str2 = "2222222222";
            $str3 = "3";
            $connection->send($str2);
            $connection->send($str1);
            $connection->send($str3);
        }
    }

发现在客户端的情况如下:
$str2接收到,$str1接收到,但是$str3没接收到,这个是个什么问题?

3418 1 0
1个回答

walkor

workerman有内存保护机制,例如向客户端发送(尤其是广播)大数据时,由于客户端接收速度或者带宽问题,客户端不会立刻接收到所有数据。那么这些未发送完的数据就要缓冲在服务器内存里。例如向1000个客户端瞬间广播10M的数据,那么最坏的情况在内存瞬间可能要缓冲10G的数据,服务器内存就爆掉了。所以workerman有一个发送缓冲区的限制,默认是每个客户端1M的缓冲区,可以通过http://doc.workerman.net/315342 更改。如果超过这个限制,会触发http://doc.workerman.net/315150回调,在这个回调里开发者可以做一些处理比如停止后续发送等。如果onBufferFull回调触发后,服务端仍然发送数据并且缓冲区仍然是满的,会触发onError回调,并丢弃数据。

通过你的代码看到是服务端瞬间发送约10M的数据,对应客户端发送缓冲区会被填满,导致后面的数据被丢弃,所以后面的数据可能收不到。
解决办法
1、不要发送这么大的数据。
2、监听onBufferFull事件,对方缓冲区满了就不要发了

年代过于久远,无法发表回答
🔝