C使用libcurl获取websocket标头字段 [英] C getting websocket header fields using libcurl

查看:199
本文介绍了C使用libcurl获取websocket标头字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如我在上一个问题中提到的(这里)我正在尝试获取websocket数据包的标头字段,特别是操作码.

As I mentioned in my previous question (here) I'm trying to get header fields of a websocket packet, opcode specifically.

正如我从RFC 6455中读到的第5.2 一样,websocket就像休假一样:

As I read from RFC 6455 Sec 5.2 a websocket is as fallows:

 0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+

因为我只对提交的操作码感兴趣,所以我创建了一个结构作为休假;

Since I'm only interested in opcode filed I created a struct as fallows;

struct websocketheader {
    uint32_t fin:1;
    uint32_t res1:1;
    uint32_t res2:1;
    uint32_t res3:1;
    uint32_t opcode:4;
    uint32_t mask:1;
    uint32_t payload_len:7;

};

如果我没有错的话

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, p_para);

这两行将传入的数据包传递给名为write_data的回调函数,其中p_para作为用户数据指针.

these two lines will pass the incoming packet to a callback function named write_data with p_para as the user data pointer.

我的write_data函数如下;

My write_data function is as follows;


static size_t write_data(void* ptr, size_t size, size_t nmemb, void *stream)
{

    struct thread_para *p_thread = (struct thread_para*)stream;
    if (p_thread) { 
        struct websocketheader wsh; 
        memcpy(&wsh,ptr,sizeof(struct websocketheader));
        switch (wsh.opcode)
        {
        case CWS_OPCODE_CONTINUATION:
            printf("opcode: continuation\n");
            break;
        case CWS_OPCODE_TEXT:
            printf("opcode text\n");
            break;
        case CWS_OPCODE_BINARY:
            printf("opcode binary\n");
        case CWS_OPCODE_CLOSE:
            printf("opcode close\n");
            break;
        case CWS_OPCODE_PING: 
            printf("opcode ping\n");
            break;
        case CWS_OPCODE_PONG:
            printf("opcode pong\n");        
        default:
            printf("Unknown opcode\n");
            break;
        }

        pthread_mutex_lock(&p_thread->lock);
        p_thread->now += size * nmemb;
        pthread_mutex_unlock(&p_thread->lock);
                 
    }
    return size * nmemb;
}

我期望正确地将前16位写入到我的结构中,但打印结果显示情况并非如此.我目前正在打印随机操作码,这表明我无法正确读取操作码.

I was expecting to get first 16 bits written to my struct correctly but the prints showed me that is not the case. I'm currently printing random opcodes which indicates I have failed to read the opcodes correctly.

正如我在上一个问题中提到的那样,我对有效负载的兴趣为零,因为它们是垃圾,并且由于我可以通过 size * nmemb 从libcurl获取总长度,因此我也对有效负载长度字段不感兴趣websocket标头.我不知道自己在做什么错,而且我对如何使用钻头的知识也知之甚少.

As I mentioned in my previous question I have zero interest in payloads since they are garbage and since I can get total length from libcurl via size * nmemb, I also have no interest the payload length field of websocket header. I have no idea what I'm doing wrong and I have limited knowledge on how to work with bits.

如果您能指出我做错了什么,并且还提出其他建议以不同的方式来完成工作,我将不胜感激.

I would really appreciate if you can point me out what I'm doing wrong and I'm also open other suggestions which would do the job in a different way.

推荐答案

不幸的是,您不能简单地做到这一点.

Unfortunately, you can't do it this simply.

您已经假定在该回调中始终至少获得 sizeof(struct websocketheader)个字节,但实际情况并非如此.您得到 size * nmemb 个字节.TCP/IP是一种流协议.

You've assumed that you always get at least sizeof(struct websocketheader) bytes in that callback, but that is not the case. You get size * nmemb bytes. TCP/IP is a stream protocol.

您需要将接收到的字节添加到缓冲区中,然后在您有足够的字节数时仅解析websocket帧.

You need to add received bytes into a buffer, then parse websocket frames only when you have enough bytes to do so.

这篇关于C使用libcurl获取websocket标头字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆