Websocket:如何编码要发送到客户端的文本,用C表示

时间:2016-09-21 13:36:06

标签: php c websocket

我正在尝试开发一个函数,用于以正确格式的websocket数据发送来编码文本。这是PHP中的一个函数,但我不能用C语言翻译它。

private function encode($text) {
// 0x1 text frame (FIN + opcode)
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);

if($length <= 125)
    $header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
    $header = pack('CCS', $b1, 126, $length);
elseif($length >= 65536)
    $header = pack('CCN', $b1, 127, $length);

return $header.$text;
}

1 个答案:

答案 0 :(得分:1)

对官僚机构的需求较少,因此实施起来要简单得多。通常,您希望调用者提供输出缓冲区和文本大小,所以让我们这样做。

另外,要特别注意字节顺序,第二次使用pack时,PHP代码应该使用'CCn'而不是'CCS'

示例实施:

static char *hdr_fill(char *buf, unsigned int hlen, size_t plen)
{
    *buf++ = 0x81; /* b1 */

    switch (hlen) {
    case 6:
        *buf++ = 127;
        break;
    case 4:
        *buf++ = 126;
    }

    /* Store length in big endian order */
    switch (hlen) {
    case 6:
        *buf++ = plen >> 24;
        *buf++ = plen >> 16;
    case 4:
        *buf++ = plen >> 8;
    case 2:
        *buf++ = plen;
    }
    return buf;
}

size_t encode(char *buf, size_t bufsize, const char *text, size_t len)
{
    const unsigned int hdrlen = len > 65535 ? 6 : (len > 255 ? 4 : 2);
    if (bufsize < hdrlen + len)
        return 0;
    buf = hdr_fill(buf, hdrlen, len);
    memcpy(buf, text, len);
    return hdrlen + len;
}

为方便起见,它返回结果的大小。您至少需要<stddef.h>(除非您替换size_t)和<string.h>

但是,您可能希望使用分散 - 聚集方法,因为它避免了复制。在这种情况下,您只需要构建标题并调整它的向量。此外,IMO更优雅:

int setup_header(struct iovec *v, int n)
{
    /* We expect a valid buffer in v[0], and the payload in v[1+] */
    if (n < 2 || v[0]->iov_len < 6)
        return -1;

    size_t len = v[1]->iov_len;
    for (int i = 2; i < n; i++)
        len += v[n]->iov_len;

    const unsigned int hdrlen = len > 65535 ? 6 : (len > 255 ? 4 : 2);
    v[0]->iov_len = hdrlen;
    hdr_fill(v[0]->iov_base, hdrlen, len);
    return 0;
}   

在这种情况下,如果成功,返回值为零。对于这个,你需要<sys/uio.h>或同等的。