首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在tls.Dial中添加10秒超时?(没有对应于tls.DialTimeout的net.DialTimeout)

如何在tls.Dial中添加10秒超时?(没有对应于tls.DialTimeout的net.DialTimeout)
EN

Stack Overflow用户
提问于 2021-09-27 22:45:23
回答 1查看 1.6K关注 0票数 2

在Go中使用超时时,添加tls.Dial的最佳方法是什么?

我看到net包有net.DialTimeout,但不幸的是,tls包没有相应的函数。

我想我应该使用contextDialer来实现超时,但我不是围棋方面的专家,我找不到任何好的例子。

(1)我找到了tls.DialWithDialer,但我不知道如何创建配置了超时的net.Dialer

代码语言:javascript
运行
复制
func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error)

(2)我还找到了tls.DialContext,但我不知道如何使用它来实现超时。

代码语言:javascript
运行
复制
func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error)

(3)我认为可能可以使用net.DialTimeout建立初始连接,然后升级连接并继续进行TLS握手,但我找不到任何示例说明如何进行此操作。

如有任何帮助或指导,将不胜感激。

下面是我的简单程序,它连接到服务器列表并打印一些关于证书链的信息。当服务器没有响应时,此程序挂起很长时间。我只想在10秒后暂停一下。

代码语言:javascript
运行
复制
package main

import (
    "bufio"
    "crypto/tls"
    "fmt"
    "os"
)

func main() {
    port := "443"
    conf := &tls.Config{
        InsecureSkipVerify: true,
    }
    s := bufio.NewScanner(os.Stdin)
    for s.Scan() {
        host := s.Text()
        conn, err := tls.Dial("tcp", host+":"+port, conf)
        if err != nil {
            fmt.Println("Host:", host, "Dial:", err)
            continue
        }
        defer conn.Close()
        certs := conn.ConnectionState().PeerCertificates
        for _, cert := range certs {
            fmt.Println("Host:", host, "Issuer:", cert.Issuer)
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2021-09-27 23:34:52

正如您在问题中提到的,有几种选择;使用DialContext是一种常见的技术:

代码语言:javascript
运行
复制
package main

import (
    "bufio"
    "context"
    "crypto/tls"
    "fmt"
    "os"
    "time"
)

func main() {
    port := "443"
    conf := &tls.Config{
        InsecureSkipVerify: true,
    }
    s := bufio.NewScanner(os.Stdin)
    for s.Scan() {
        host := s.Text()
        ctx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
        d := tls.Dialer{
            Config: conf,
        }
        conn, err := d.DialContext(ctx,"tcp", host+":"+port)
        cancel() // Ensure cancel is always called
        if err != nil {
            fmt.Println("Host:", host, "Dial:", err)
            continue
        }

        // warning: using defer in a loop may not have the expected result
        // the connection will remain open until the function exists
        defer conn.Close()

        tlsConn := conn.(*tls.Conn)
        certs := tlsConn.ConnectionState().PeerCertificates
        for _, cert := range certs {
            fmt.Println("Host:", host, "Issuer:", cert.Issuer)
        }
    }
}

使用上述方法可以相对简单地允许代码用户取消请求(接受context,并在上面有context.Background()的地方使用)。如果这对您不重要,那么在Dialer中使用Timeout就更简单了:

代码语言:javascript
运行
复制
conn, err := tls.DialWithDialer(&net.Dialer{Timeout:  10 * time.Second}, "tcp", host+":"+port, conf)
if err != nil { 
    fmt.Println("Host:", host, "Dial:", err)
    continue
}

certs := conn.ConnectionState().PeerCertificates
for _, cert := range certs {
    fmt.Println("Host:", host, "Issuer:", cert.Issuer)
}
conn.Close()
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69353996

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档