C使用libcurl获取websocket标头字段 [英] C getting websocket header fields using libcurl
问题描述
正如我在上一个问题中提到的(这里)我正在尝试获取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屋!