不用看书就可以窥见Conn [英] Peek into Conn without reading in go

查看:62
本文介绍了不用看书就可以窥见Conn的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个服务器 net.Conn ,我想在读取字节之前先查看一下它,以检查它是客户端尝试使用的纯文本协议还是SSL/TLS.

I have a server net.Conn, and I'd like to peek into it before reading out bytes, to check if it's a plain text protocol the client is trying to use, or SSL/TLS.

检查 http://golang.org/pkg/net/,看来 Conn 界面没有这样的东西.我知道我可以使用 iobuf.Reader ,但是我想通过 tls.Conn(conn,config)获取TLS Conn,前提是客户端是使用SSL/TLS,并且 bufio.Reader 将从原始的 Conn 中读取,因此在 tls.Conn 中的握手将失败.

Checking http://golang.org/pkg/net/, it seems the Conn interface does not have anything like that. I know I could use an iobuf.Reader, but I'd like to get a TLS Conn via tls.Conn(conn, config) if it turns out the client is using SSL/TLS, and bufio.Reader would read from the original Conn, thus the handshake in tls.Conn would fail.

那么有什么方法可以窥探Go中的 Conn (类似于C/C ++套接字中的 MSG_PEEK )吗?或者,要在我从底层的 Conn 中读出前几个字节后创建一个 tls.Conn ?

So is there any way to peek into a Conn in Go (something like MSG_PEEK in C/C++ sockets)? Or, to create a tls.Conn after I had read out the first few bytes from the underlying Conn?

推荐答案

您非常接近解决方案-唯一的错误是首先从 Conn 本身读取内容.您认为 bufio.Reader Peek 方法是正确的.诀窍是先使缓冲的读取器成为对象,然后在缓冲的读取器上调用 Peek ,而不是从原始的 Conn 中读取.这是一个 bufferedConn 类型,可以满足您的需求:

You're very close to a solution - the only thing you got wrong was reading from the Conn itself first. You are right that bufio.Reader's Peek method is the way to go. The trick is to make the buffered reader first and call Peek on the buffered reader rather than reading from the original Conn. Here's a bufferedConn type that will do what you need:

type bufferedConn struct {
    r        *bufio.Reader
    net.Conn // So that most methods are embedded
}

func newBufferedConn(c net.Conn) bufferedConn {
    return bufferedConn{bufio.NewReader(c), c}
}

func newBufferedConnSize(c net.Conn, n int) bufferedConn {
    return bufferedConn{bufio.NewReaderSize(c, n), c}
}

func (b bufferedConn) Peek(n int) ([]byte, error) {
    return b.r.Peek(n)
}

func (b bufferedConn) Read(p []byte) (int, error) {
    return b.r.Read(p)
}

它的作用是允许您访问所有常规的 net.Conn 方法(通过嵌入 net.Conn -您也可以编写包装函数,但这更加容易和清洁),并且还提供对 bufferedReader Peek Read 方法的访问(重要的是, Read bufferedReader 上被调用,而不是直接在 net.Conn 上被调用,因为 Peek 将数据存储在缓冲区中,因此后续调用 Read 需要首先能够从此缓冲区中读取任何数据,然后再回到基础的 net.Conn ).

What this does is allow you to access all of the normal net.Conn methods (by embedding the net.Conn - you could also write wrapper functions, but this is a lot easier and cleaner), and additionally provide access to the bufferedReader's Peek and Read methods (it's important that Read be called on the bufferedReader, not directly on the net.Conn because Peek stores data in a buffer, so subsequent calls to Read need to be able to first read any data out of this buffer before falling back to the underlying net.Conn).

鉴于当前的默认缓冲区大小为4096个字节,可能没有必要使用 newBufferedConnSize 函数,但是从技术上讲,如果您要依赖能够使用以下命令调用 Peek 给定的大小,但没有返回错误(具体是 ErrBufferFull ),则应将其显式设置为至少与打算窥视的字节数一样大的大小.

The newBufferedConnSize function is probably unnecessary given that the current default buffer size is 4096 bytes, but technically if you're going to rely on being able to call Peek with a given size and not have it return an error (specifically ErrBufferFull), you should set it explicitly to a size that's at least as big as the number of bytes you intend to peek.

转到游乐场中进行检查.

这篇关于不用看书就可以窥见Conn的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆