如何使用 tls.Dial 添加 10 秒超时? (没有tls.DialTimeout对应net.DialTimeout)
Posted
技术标签:
【中文标题】如何使用 tls.Dial 添加 10 秒超时? (没有tls.DialTimeout对应net.DialTimeout)【英文标题】:How can I add a 10 second timeout with tls.Dial ? (There is no tls.DialTimeout to correspond to net.DialTimeout) 【发布时间】:2021-11-20 00:56:27 【问题描述】:在 Go 中使用 tls.Dial
时添加超时的最佳方法是什么?
我看到net
包有net.DialTimeout
,可惜tls
包没有对应的功能。
我想我应该使用context
或Dialer
来实现超时,但我不是围棋专家,我找不到任何好的例子。
(1) 我找到了tls.DialWithDialer
,但我不确定如何创建一个配置了超时的net.Dialer
。
func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error)
(2) 我也找到了tls.DialContext
,但我不确定如何使用它来实现超时。
func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error)
(3) 我认为可以使用 net.DialTimeout
建立初始连接,然后升级连接并继续 TLS 握手,但我找不到任何示例说明如何做到这一点。
任何帮助或指导将不胜感激。
这是我的简单程序,它连接到服务器列表并打印有关证书链的一些信息。当服务器没有响应时,该程序会挂起很长时间。我只想在 10 秒后超时。
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)
【问题讨论】:
【参考方案1】:正如您在问题中提到的,有几个选项;使用DialContext
是一种常用技术:
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
会更简单:
conn, err := tls.DialWithDialer(&net.DialerTimeout: 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()
【讨论】:
以上是关于如何使用 tls.Dial 添加 10 秒超时? (没有tls.DialTimeout对应net.DialTimeout)的主要内容,如果未能解决你的问题,请参考以下文章
向 DatagramSocket 添加超时-receive()
如何使用 NSURLConnection (NSMutableRequest) 超时