使用Golang从net.TCPConn读取字节,并使用4个字节作为消息分隔符。

huangapple go评论82阅读模式
英文:

golang read bytes from net.TCPConn with 4 bytes as message separation

问题

我正在使用golang开发SIP over TCP的模拟服务。传入的SIP消息是通过'\r\n\r\n'序列分隔的(我现在不关心SDP)。我想根据这个分隔符提取消息并将其发送到处理goroutine中。浏览了golang标准库,我发现没有简单的方法可以实现这一点。在iobufio包中似乎没有一个统一的解决方案。目前我看到两种继续前进的选项(使用bufio):

  1. 使用Reader.ReadBytes函数,将'/r'设置为分隔符。进一步的处理可以使用ReadByte函数,并将其与分隔符的每个字节逐个比较,如果需要的话可以取消读取它们(这看起来相当繁琐)。

  2. 使用自定义的分割函数来使用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):

  1. *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)

  2. 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
}

huangapple
  • 本文由 发表于 2016年12月21日 06:13:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/41252089.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定