gpt4 book ai didi

使用 socket_recv() 的 PHP websocket - 我会收到部分帧吗?

转载 作者:行者123 更新时间:2023-12-03 11:52:57 25 4
gpt4 key购买 nike

我正在用 PHP 编写一个 websocket 服务器(使用 sockets 扩展),我需要一些帮助来了解我需要在多大程度上处理碎片消息。

我对websocket信息如何传递的理解如下:

  • 客户端应用程序发送 MESSAGE (任意长度)到客户端 API。
  • 客户端 API 拆分 MESSAGE变成一个或多个 FRAMES (也是任意长度)并将它们发送到网络层。
  • 网络层将数据拆分成若干PACKETS通过 TCP 通过网络发送。
  • 服务器收到 TCP PACKETS (可能是无序的,但如有必要,它会重新排序)并将它们传递给正在监听相关端口的应用程序。
  • 应用程序调用 socket_recv()从套接字读取接收到的数据。

  • 我想了解的是 使用 socket_recv() 读取 websocket 数据流时,我的应用程序将看到什么数据?

    具体来说,我需要在多大程度上担心碎片化?

    为了帮助解释我的问题,以下是上述过程的图表形式:

    1. Web app  (messages):   [Message_1][Message_2]
    2. Browser (frames) : [Messag][e_1][Messag][e_2]
    3. TCP send (packets) : [Mess][ag][e_1][Mess][ag][e_2]
    4. TCP recv (packets) : [ag][Mess][e_2][ag][Mess][e-1]
    5. socket_recv : ???

    如果我调用 socket_recv()在一个循环中,直到它返回零长度(每次都添加到我的内部缓冲区),我保证得到一个完整的 MESSAGE ?

    socketrecv: [Message_1]
    socketrecv: [Message_2]

    或单个完整的 FRAME ?

    socketrecv: [Messag]
    socketrecv: [e_1]
    socketrecv: [Messag]
    socketrecv: [e_2]

    或者,它实际上是 PACKETS 的任意序列吗?表示到目前为止已收到的任何数据(因此可能是部分 FRAME 甚至是多个 FRAMES )?

    socketrecv: [Messag
    socketrecv: e_1][Mess
    socketrecv:
    socketrecv: ag
    socketrecv: e_2]

    或者是其他东西?

    我很高兴将各种 FRAMES 拼接在一起数据,但如果我可以假设每次轮询中接收到的数据的第一个字节(使用 socket_select() 发起)将始终是 FRAME头,而不必将其作为需要缝合回 FRAMES 的原始字节流处理在我们开始之前。

    最佳答案

    哦,好吧,我曾经在我的 C++ 代码中使用 websocket,是的,由于 TCP 协议(protocol)的工作方式,它可能会被分割。

    websocket 有两种类型的数据流:Hixie(旧),Hybi(新),还有版本,例如 hybi-13 .. hybi-17。

    但没关系,因为您的问题是 socket_recv() 仅从缓冲区检索数据,缓冲区取决于您的网络设置(MTU)以及操作系统和硬件......如此复杂......甚至可以读取 1 字节16MB 也是。

    因此,如果您想在 PHP 中实现 websocket,则必须读取并解析框架并获取其大小,如果大小可用,则剪切并处理然后继续,如果没有阅读更多内容。

    很有可能收到不完整的帧或一帧和不完整的下一帧。
    因此,您必须跨过并找到帧的开头,计算它的大小并向前迈进,如果您有剩余的数据必须保留在缓冲区(也称为变量)中,并且必须在之后附加下一个读数。

    但首先,您必须首先读取至少 4 个字节。 (标题大小)
    很高兴知道 hybi 协议(protocol)使用“压缩”,因此使用有效负载的 crafeul 帧字节可能会根据其整数类型而有所不同。

    请参阅下面的 C 代码。

            payload_length = frame[1] & 0x7f;
    if (payload_length < 126)
    {
    hdr_length = 2;
    payload_length = payload_length; // FYI / DUMMY
    }
    else if (payload_length == 126)
    {
    payload_length = (frame[2] << 8) + frame[3];
    hdr_length = 4;
    }
    else
    ....

    关于使用 socket_recv() 的 PHP websocket - 我会收到部分帧吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46720022/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com