你可以如何调用TCPConn.SetLinger()方法?

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

How do I call TCPConn.SetLinger()?

问题

我正在使用Go 1.2,并尝试在我的服务器关闭由于输入中的致命错误而关闭的套接字上调用TCPConn.SetLinger(0)。然而,我无法弄清楚如何做到这一点。net.Listener.Accept()和TCPListener.Accept()都返回net.Conn,而不是net.TCPConn。net.Conn没有实现SetLinger。我尝试进行类型切换,但编译器抱怨"不可能的类型切换情况:conn(类型为net.Conn)不能具有动态类型net.TCPConn(缺少Close方法)"。net.TCPConn怎么会缺少Close方法呢?我还没有检查过源代码,但文档中列出了一个close方法(反正你无论如何都可以关闭连接)。

看起来你不能将net.Conn转换为net.TCPConn(因为没有Close方法),而且你无法从服务器获取TCPConn,因为所有的Accept()都返回net.Conn。那么我该如何调用SetLinger呢?(或者说,SetKeepAlive、SetNoDelay呢?)

仔细查看后,似乎有一个net.TCPListener.AcceptTCP()方法,它返回一个TCPListener,我真的需要这样做吗?为什么我不能从Accept()中获取TCPConn呢?我开始使用net.Listen("tcp", ":4321"),所以我知道它必须是一个TCPConn...

英文:

I'm using Go 1.2 and trying to call TCPConn.SetLinger(0) on a socket that my server is closing due to fatal errors in the input. However, I can't figure out how I would do this. Both net.Listener.Accept() and TCPListener.Accept() return net.Conn, not net.TCPConn. net.Conn does not implement SetLinger. I tried doing a type switch, but then the compiler complains of an "impossible type switch case: conn (type net.Conn) cannot have dynamic type net.TCPConn (missing Close method)". How can net.TCPConn be missing a Close method?? I haven't checked the source, but the documentation lists a close method (and what kind of connection can you not close, anyway?).

It seems like you cannot cast net.Conn to net.TCPConn (because of no Close method), and you can't get a TCPConn on a server, because all the Accept()s return a net.Conn. So how do I actually call SetLinger? (Or for that matter, SetKeepAlive, SetNoDelay?)

After looking more closely, it looks like there is a net.TCPListener.AcceptTCP() which returns a TCPListener, is that really what I have to do? Why can't I get a TCPConn from Accept()? I started it off with net.Listen("tcp", ":4321"), so I know it has to be a TCPConn underneath...

答案1

得分: 3

你可以使用TCPListener.AcceptTCP()方法,Accept方法只是调用AcceptTCP方法并将*TCPConn作为接口返回。

从http://golang.org/src/pkg/net/tcpsock_posix.go?s=7727:7771#L233

func (l *TCPListener) Accept() (Conn, error) {
    c, err := l.AcceptTCP() //注意这部分
    if err != nil {
        return nil, err
    }
    return c, nil
}

或者像James在评论中提到的那样,你可以简单地将其转换为tcpcon := conn.(*net.TCPConn)

英文:

You could use TCPListener.AcceptTCP(), Accept just calls AcceptTCP and returns *TCPConn as an interface.

From http://golang.org/src/pkg/net/tcpsock_posix.go?s=7727:7771#L233

func (l *TCPListener) Accept() (Conn, error) {
	c, err := l.AcceptTCP() //notice this part
	if err != nil {
		return nil, err
	}
	return c, nil
}

Or like James mentioned in the comments, you could simply cast it to tcpcon := conn.(*net.TCPConn).

答案2

得分: 0

根据如何设置Go net/http的Socket选项 - setsockopt()示例,我们可以通过net.DialerControl来设置SO_LINGER

另一种解决方案是通过http.TransportDialContext来完成。

以上是要翻译的内容。

英文:

Per How to Set Go net/http Socket Options - setsockopt() example

We could set SO_LINGER through Control of net.Dialer

	dialer := &net.Dialer{
		Control: func(network, address string, conn syscall.RawConn) error {
			var operr error
			if err := conn.Control(func(fd uintptr) {
				operr = syscall.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_LINGER, 1)
			}); err != nil {
				return err
			}
			return operr
		},
	}

	client := http.Client{Transport: &http.Transport{DialContext: dialer.DialContext}}

Another solution could be done through DialContext of http.Transport

type connDialer struct {
	c net.Conn
}

func (cd connDialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
	tcpConn, ok := cd.c.(*net.TCPConn)
	if ok {
		tcpConn.SetLinger(0)
		return tcpConn, nil
	}
	return cd.c, nil
}

dialer := net.Dialer{}
conn, _ := dialer.DialContext(ctx, network, addr)

client := http.Client{Transport: &http.Transport{DialContext: connDialer{c: conn}.DialContext}}

huangapple
  • 本文由 发表于 2014年7月22日 12:16:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/24878823.html
匿名

发表评论

匿名网友

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

确定