英文:
golang read bytes from net.TCPConn with 4 bytes as message separation
问题
我正在使用golang开发SIP over TCP的模拟服务。传入的SIP消息是通过'\r\n\r\n'序列分隔的(我现在不关心SDP)。我想根据这个分隔符提取消息并将其发送到处理goroutine中。浏览了golang标准库,我发现没有简单的方法可以实现这一点。在io
和bufio
包中似乎没有一个统一的解决方案。目前我看到两种继续前进的选项(使用bufio):
-
使用
Reader.ReadBytes
函数,将'/r'设置为分隔符。进一步的处理可以使用ReadByte
函数,并将其与分隔符的每个字节逐个比较,如果需要的话可以取消读取它们(这看起来相当繁琐)。 -
使用自定义的分割函数来使用
Scanner
,这也不是太简单。
我想知道是否有其他更好的选项,功能似乎很常见,很难相信不能只定义TCP流的分隔符并从中提取消息。
英文:
I am working on SIP over TCP mock service in golang. Incoming SIP messages are separated by '\r\n\r\n' sequence (I do not care about SDP for now). I want to extract message based on that delimiter and send it over to the processing goroutine. Looking through golang standard libraries I see no trivial way of achieving it. There seems to be no one shop stop in io
and bufio
packages. Currently I see two options of going forward (bufio):
-
*Reader.ReadBytes function with '/r' set as the delimiter. Further processing is done by using ReadByte function and comparing it sequentially with each byte of the delimiter and unreading them if necessary (which looks quite tedious)
-
Using Scanner with a custom split function, which does not look too trivial as well.
I wonder whether there are any other better options, functionality seems so common that it is hard to believe that it is not possible to just define delimiter for tcp stream and extract messages from it.
答案1
得分: 1
你可以选择自己缓冲读取并在 \r\n\r\n
分隔符处进行分割,或者让 bufio.Scanner
来完成。实现一个 scanner.SplitFunc
并不困难,而且比另一种方法更简单。以使用 bufio.ScanLines
为例,你可以这样使用:
scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
delim := []byte{'\r', '\n', '\r', '\n'}
if atEOF && len(data) == 0 {
return 0, nil, nil
}
if i := bytes.Index(data, delim); i >= 0 {
return i + len(delim), data[0:i], nil
}
if atEOF {
return len(data), data, nil
}
return 0, nil, nil
})
英文:
You can either choose to buffer the reads up yourself and split on the \r\n\r\n
delimiter, or let a bufio.Scanner
do it for you. There's nothing onerous about implementing a scanner.SplitFunc
, and it's definitely simpler than the alternative. Using bufio.ScanLines
as an example, you could use:
scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
delim := []byte{'\r', '\n', '\r', '\n'}
if atEOF && len(data) == 0 {
return 0, nil, nil
}
if i := bytes.Index(data, delim); i >= 0 {
return i + len(delim), data[0:i], nil
}
if atEOF {
return len(data), data, nil
}
return 0, nil, nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论