英文:
When I send 127+ characters from chrome websocket, my golang server cannot see more than 126
问题
我正在翻译以下内容:
我正在兴致勃勃地重新发明轮子,并玩弄比特来实现一个简单的服务器。它几乎可以正常工作了,但我不确定这个问题是我的客户端还是我的服务器引起的。下面是我在net.Conn Read函数中传递结果字节数组的部分代码:
func readWsFrame(p []byte) {
// 处理第一个字节
b := p[0]
fmt.Printf("第一个字节:%b\n", b)
fin := b & 128 // 希望是128,表示fin
op := b & 15 // 希望是1,表示文本
fmt.Printf("fin:%d\nop:%d\n", fin, op)
// 处理第二个字节
b = p[1]
fmt.Printf("第二个字节:%b\n", b)
masked := b & 128 // 表示负载是否经过掩码处理
length := b & 127 // 负载长度
fmt.Printf("masked:%d\nlength:%d\n", masked, length)
// 处理第3到第7个字节(掩码密钥)
key := p[2:6]
// 负载
d := p[6:]
if length == 126 {
key = p[4:8]
d = p[8:]
fmt.Println("中等长度的密钥")
} else if length == 127 {
key = p[10:14]
d = p[14:]
fmt.Println("较大长度的密钥")
} else {
fmt.Println("较小长度的密钥")
}
fmt.Printf("掩码密钥:%b\n", key)
fmt.Printf("掩码数据:%b\n", d)
var decoded []byte
for index := 0; index < int(length); index++ {
decoded = append(decoded, d[index]^key[index%4])
}
fmt.Printf("解码后的数据:%b\n", decoded)
payload := string(decoded)
fmt.Println("负载:", payload)
}
客户端代码是我在浏览器的开发控制台中运行的:
var ws = new WebSocket("ws://localhost:16163");
ws.send("a".repeat(125));
ws.send("a".repeat(126));
ws.send("a".repeat(127));
ws.send("a".repeat(400));
我的服务器在处理127个字符之前都符合我的预期。但是,当长度超过126时,我的第二个字节是11111110,而长度是126。我可以看到未经掩码/编码/魔术处理的消息不会超过126个a。
我确信我的Go代码可能不够好,可能有一些明显的问题,但我正在查看比特位本身,我发现在我期望为1的位置上有一个0,请帮助我,谢谢!
--编辑:
我意识到根据我那里的循环,我永远不会看到超过126个字符,但是对于这些更大的消息,我仍然应该在第二个字节的最后一位看到一个1,对吗?
--编辑:
我看到了这个问题:https://stackoverflow.com/questions/18271598/how-to-work-out-payload-size-from-html5-websocket
我想我可能误解了我之前搜索到的所有内容。有人可以确认一下吗?如果长度小于126,则长度为字节与127的按位与。如果长度为126,则长度为下两个字节的值。如果长度为127,则长度为下4个字节的值。
我最初以为如果负载长度为127+,那么长度将为127,哈哈,我错了。所以当长度为126或127时,第二个字节不是实际长度的一部分?我可能会通过测试来确认所有这些,但在周末之前,感谢大家解决了这个问题,这样我就可以完成这个副项目了。
英文:
I'm having a blast reinventing the wheel and playing with bits to implement a simple server. It's almost functional, but I'm not sure if this issue is my client or my server. Here is the function where I pass the resulting byte array from net.Conn Read
func readWsFrame(p []byte) {
// process first byte
b := p[0]
fmt.Printf("first byte: %b\n", b)
fin := b & 128 // hopefully 128, for fin
op := b & 15 // hopefully 1, for text
fmt.Printf("fin: %d\nop: %d\n", fin, op)
// process second byte
b = p[1]
fmt.Printf("second byte: %b\n", b)
masked := b & 128 // whether or not the payload is masked
length := b & 127 // payload length
fmt.Printf("masked: %d\nlength: %d\n", masked, length)
// process bytes 3-7 (masking key)
key := p[2:6]
// payload
d := p[6:]
if length == 126 {
key = p[4:8]
d = p[8:]
fmt.Println("med key")
} else if length == 127 {
key = p[10:14]
d = p[14:]
fmt.Println("big key")
} else {
fmt.Println("lil key")
}
fmt.Printf("masking key: %b\n", key)
fmt.Printf("masked data: %b\n", d)
var decoded []byte
for index := 0; index < int(length); index++ {
decoded = append(decoded, d[index]^key[index%4])
}
fmt.Printf("unmasked data: %b\n", decoded)
payload := string(decoded)
fmt.Println("payload: ", payload)
}
The client code is me having the dev console open right off this web page and running
var ws = new WebSocket("ws://localhost:16163");
ws.send("a".repeat(125))
ws.send("a".repeat(126))
ws.send("a".repeat(127))
ws.send("a".repeat(400))
My server is doing what I expect until I reach 127 characters. At that point, and every amount over 126, my 2nd byte is 11111110 and the length is 126. I can see the unmasked/encoded/magic message doesn't go beyond 126 a's.
I'm sure my go code is sub-par and there might be something obvious here, but I'm looking at the bits themselves, and I can see a 0 where I am expecting a 1, please help me, thank you!
I saw a similar question about writing messages larger than 126 bytes and how I'll need extra bytes for payload size, but in this case my client is the chrome web browser.
--edit:
I realize that I will never see more than 126 characters based on the loop I have there, but I should still see a 1 in the final bit in the second byte for these larger messages, right?
--edit:
Came across this https://stackoverflow.com/questions/18271598/how-to-work-out-payload-size-from-html5-websocket
I guess I misunderstood everything else I was searching for. Can someone confirm this? If the length is <126, the length is byte & 127. If the length is 126, the length is the value of the next 2 bytes. If the length is 127, the length is the next 4 bytes.
I thought initially that the length would be 127 if it payload length was 127+ hah, oops. So when the length is 126 or 127, the 2nd byte is not part of the actual length? I'll probably confirm all of this with testing, but I thank you all for resolving this issue before the weekend so I can finish this side project.
答案1
得分: 0
代码在读取后续字节中的长度数据后,应该在意识到长度为127或126时更新长度属性。
对于这7个“长度”位,我会稍微不同地解释。它们并不真正表示长度,而是表示编码方式。
如果长度使用64位(8字节)进行编码,则长度指示符为127。
如果长度使用2字节进行编码,则指示符为126。
否则,长度将在指示符本身的7位中进行编码。
例如,长度60可以用这三种方式编码(尽管某些方式使用更多的空间)。
如果你想要阅读一个解码长度的示例,可以参考这里的C Websocket实现。
祝你好运!
英文:
The code should update the length property after realizing it's 127 or 126 by reading the length data in the bytes that follow the initial length indicator.
I would consider those 7 "length" bits slightly differently. They don't really indicate length as much as they indicate encoding.
If the length is encoded using 64bits (8 bytes), than the length indicator == 127.
If the length is encoded in 2 bytes, than the indicator == 126.
Otherwise, the length is encoded in the 7 bits of the indicator itself.
For example, the length 60 can be encoded in all three ways (albeit, some use more space).
There's a C Websocket implementation here if you want to read an example decoding of the length.
Good Luck!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论