Websocket 数据取消屏蔽/多字节异或
Posted
技术标签:
【中文标题】Websocket 数据取消屏蔽/多字节异或【英文标题】:Websocket data unmasking / multi byte xor 【发布时间】:2013-07-19 09:34:08 【问题描述】:websocket 规范将取消屏蔽数据定义为
j = i MOD 4
transformed-octet-i = original-octet-i XOR masking-key-octet-j
其中掩码为 4 个字节长,并且必须对每个字节应用取消掩码。
有没有比循环字节更有效的方法?
可以假设运行代码的服务器是 Haswell CPU,操作系统是内核 > 3.2 的 Linux,因此 SSE 等都存在。编码是用 C 完成的,但如果需要,我也可以做 asm。
我曾尝试自己查找解决方案,但无法确定是否在数十个 SSE1-5/AVE/ 中的任何一个中都存在适当的指令(无论扩展名 - 多年来都失去了踪迹)
非常感谢!
编辑:在重新阅读规范几次之后,它似乎实际上只是对数据字节与掩码字节进行异或运算,我可以一次执行 8 个字节,直到最后几个字节。问题仍然悬而未决,因为我认为可能仍有一种方法可以使用 SSE 或类似方法来优化它(可能一次处理甚至 16 个字节?让进程执行 for 循环?...)
【问题讨论】:
【参考方案1】:是的,您可以使用 SSE2 在一条指令中异或 16 个字节,或者使用 AVX2(Haswell 及更高版本)一次异或 32 个字节。
SSE2:
#include <emmintrin.h> // SSE2 instrinsics
__m128i v, v_mask;
uint8_t *buff; // buffer - must be 16 byte aligned
for (int i = 0; i < N; i += 16) // note that N must be multiple of 16
v = _mm_load_si128(&buff[i]); // load 16 bytes
v = _mm_xor_si128(v, v_mask); // XOR with mask
v = _mm_store_si128(&buff[i], v); // store 16 masked bytes
AVX2:
#include <immintrin.h> // AVX2 intrinsics
__m256i w, w_mask;
uint8_t *buff; // buffer - must be 16 byte aligned,
// and preferably 32 byte aligned
for (int i = 0; i < N; i += 32) // note that N must be multiple of 32
w = _mm256_load_si256(&buff[i]); // load 32 bytes
w = _mm256_xor_si256(w, w_mask); // XOR with mask
w = _mm256_store_si256(&buff[i], w); // store 32 masked bytes
【讨论】:
非常感谢!一旦我测试它工作,我会接受这个作为答案! 目前正试图将其放入我在谷歌上发现的代码中,使用的指针应始终与处理大小对齐 - 这意味着在 AVX2 的情况下它应该是 32 字节对齐 - 如果我没记错的话在那里,你可能想在你的代码 cmets 中更正它! @griffin:使用 AVX/AVX2 稍微复杂一些 - SSE 绝对需要 16 字节对齐,而 AVX/AVX2 可以使用 16 字节对齐(即使对于 32 字节加载/存储),但可能在某些情况下使用 32 字节对齐提供更好的性能。我已经更新了评论。 最好还是只使用序言/尾声,避免在处理不佳的处理器上使用未对齐的负载来轰炸性能。但是,如果您有 AVX,我想所有处理器都支持快速未对齐负载......(至少我遇到过的那些)。以上是关于Websocket 数据取消屏蔽/多字节异或的主要内容,如果未能解决你的问题,请参考以下文章
如何在 netty4 中设置 Web 套接字客户端未屏蔽模式文本框
PHP Websocket 服务器 - 在 socket_recv 中处理更多帧