简体   繁体   English

如何在C中使用zlib库对websocket permessage-deflate进行编码和解码?

[英]How to Encode and Decode websocket permessage-deflate using zlib library in C?

All I am trying to encode WebSocket payload using per-message-deflate. 我试图使用per-message-deflate编码WebSocket有效负载。 I am trying to use some test code but my encoding is not proper can you please help me. 我试图使用一些测试代码,但我的编码不正确,请你帮我。

Here is my code: 这是我的代码:

char a[180] = "{\"type\":\"message\",\"channel\":\"C04U0F9CW\",\"text\":\"TestingMessage\",\"id\":757}";
char b[180];
char c[180];
int i;
// deflate
// zlib struct
z_stream defstream;
defstream.zalloc = Z_NULL;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
defstream.avail_in = (uInt)strlen(a)+1; // size of input, string + terminator
defstream.next_in = (Bytef *)a; // input char array
defstream.avail_out = (uInt)sizeof(b); // size of output
defstream.next_out = (Bytef *)b; // output char array

//deflateInit(&defstream, Z_SYNC_FLUSH);
deflateInit2(&defstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY);
deflate(&defstream, Z_SYNC_FLUSH);
deflateEnd(&defstream);
for(i=0;i<=(char*)defstream.next_out - b;i++)
{
        printf("%X",(Bytef)b[i]);
}
printf("\n%s\n",(Bytef *)b);
// This is one way of getting the size of the output
printf("Deflated size is: %lu\n", (char*)defstream.next_out - b);

my output is 我的输出是

kml@kml-VirtualBox:~/zlib-1.2.11/test$ gcc test.c -lz && ./a.out 
789CAA562AA92C4855B252CA4D2D2E4E4C4F55D2514ACE48CCCB4BCD18A391B98841AB8593A873454B522B4A804221A9C5259979E9BE70D599294A56E6A6E6B5C0000FFFF2E
x��V*�,HU�R�M-.NLOU�QJ�H��K��9���Y:�EKR+J�B!��%�y��pՙ)JV����

Deflated size is: 72
Inflate:
73
{"type":"message","channel":"C04U0F9CW","text":"TestingMessage","id":757}

So I am expecting payload will me like this 所以我期待有效载荷让我这样

AA562AA92C4855B252CA4D2D2E4E4C4F55D2514ACE48CCCB4BCD018A391B98841AB8593A8703454B522B4A804221A9C5259979E9BE70D599294A56E6A6E6B50000

This is the fiddler WebSocket traffic capture for that particular message 这是该特定消息的fiddler WebSocket流量捕获

Please help me out to get proper per-message-deflate encoding. 请帮助我获得正确的per-message-deflate编码。

Here is some more upgrade information
GET https://127.0.0.1/websoc.html HTTP/1.1
Host: mpmulti-yklu.slack-msgs.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: FriWg0AWhiLhLXXnfJK8kA==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

Response 响应

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: S2Q+O/tRM0/mIG//Er2hDdqD0eY=
Sec-Websocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover
X-Via: haproxy-ext90

The code is correct but defstream.avail_in expect exact length, not for the extra null character. 代码是正确的,但defstream.avail_in期望精确的长度,而不是额外的空字符。 If you will provide exact input length it will work properly. 如果您将提供确切的输入长度,它将正常工作。 Try like this 试试这样吧

int l = (uInt)strlen(a);
defstream.avail_in = l; // size of input, string + terminator

Please try to understand how z_stream is assigning value check the code then you will better understand about this. 请尝试了解z_stream如何分配值检查代码,然后您将更好地了解这一点。

I think many people are trying the decode and they are not getting proper value for per-message-deflate. 我想很多人都在尝试解码,而且他们没有为每个消息放弃获得适当的价值。

Check your output 检查你的输出

" 789CAA562AA92C4855B252CA4D2D2E4E4C4F55D2514ACE48CCCB4BCD18A391B98841AB8593A873454B522B4A804221A9C5259979E9BE70D599294A56E6A6E6B5C0000FFFF2E " 789CAA562AA92C4855B252CA4D2D2E4E4C4F55D2514ACE48CCCB4BCD18A391B98841AB8593A873454B522B4A804221A9C5259979E9BE70D599294A56E6A6E6B5C0000FFFF2E

Here 789C is header and 0000FFFF or according to your code (00FFFF) is the trailer of deflate message. 这里789C是标题和0000FFFF或根据你的代码(00FFFF)是deflate消息的预告片。 here 0 is for 00 because your output is print one '0' instead of '00'. 这里0代表00,因为你的输出是打印一个'0'而不是'00'。 you are getting 5C extra because of extra one size. 因为额外的一个尺码,你得到额外的5C。 Thye '2E' will also will be removed when you will try below code 当您尝试下面的代码时,Thye'2E'也将被移除

int d = memcmp(msgend, &b[defstream.total_out - 4], 4) ? 0 : 4;
for(i=0;i<defstream.total_out - d;i++)
{
        printf("%2X",(Bytef)b[i]);
}

So your expected answer is 所以你的预期答案是

" AA562AA92C4855B252CA4D2D2E4E4C4F55D2514ACE48CCCB4BCD018A391B98841AB8593A8703454B522B4A804221A9C5259979E9BE70D599294A56E6A6E6B50000 " AA562AA92C4855B252CA4D2D2E4E4C4F55D2514ACE48CCCB4BCD018A391B98841AB8593A8703454B522B4A804221A9C5259979E9BE70D599294A56E6A6E6B50000

As per your output, 2 bytes are 0 so as per your code it will be '00' and your output follow printing each nibble (half byte). 根据您的输出,2个字节为0,因此根据您的代码,它将为“00”并且您的输出跟随打印每个半字节(半字节)。

Please try this is worked for me and I am now able to decode properly. 请尝试这对我有用,我现在能够正确解码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM