gpt4 book ai didi

http - 如何用go语言为http客户端设置套接​​字选项(IP_TOS)?

转载 作者:IT王子 更新时间:2023-10-29 01:01:55 26 4
gpt4 key购买 nike

我是 Go 语言的新手。我打算用go语言开发一个http客户端/服务器。在浏览 http 客户端包中支持的功能列表时,我找不到在包中设置套接字选项的方法(可能我只是不知道如何使用它)。在调用 http 客户端连接之前,我需要在 fd 中设置 DSCP 选项(IP_TOS)。(虽然我找到了设置套接字选项的系统调用选项,但我没有找到从 http 包中获取 fd 的方法)。

在http服务器端,可以设置套接字选项(IP_TOS)。代码摘录:

       tcpListener,err := net.ListenTCP("tcp4", addr)
if err != nil {
//fmt.Println("error in listen", err.error())
log.Fatal("net.ListenTCP()", err)
}
//get lisenet socket fd
f, _ := tcpListener.File()
err = syscall.SetsockoptInt(int(f.Fd()), syscall.SOL_SOCKET, syscall.IP_TOS, 128)

在 http 客户端 无法获取套接字 fd 和设置套接字选项 (IP_TOS):(我想在调用NewRequest之前设置IP_TOS)

     client := &http.Client{
Transport : tr,
//Timeout: time.Duration(10) * time.Second,
}

request, err := http.NewRequest("POST", url, body)
if err != nil {
panic(err)
}

response, err := client.Do(request)

谢谢!!

最佳答案

您可以为自己的 *http.Clienthttp.RoundTripper 创建自己的 DialContext:

dial := func(ctx context.Context, network, addr string) (net.Conn, error) {
conn, err := (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext(ctx, network, addr)
if err != nil {
return nil, err
}

tcpConn, ok := conn.(*net.TCPConn)
if !ok {
err = errors.New("conn is not tcp")
return nil, err
}

f, err := tcpConn.File()
if err != nil {
return nil, err
}

err = syscall.SetsockoptInt(int(f.Fd()), syscall.IPPROTO_IP, syscall.IP_TOS, 128)
if err != nil {
return nil, err
}

return conn, nil
}
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: dial,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
c := &http.Client{
Transport: tr,
}
resp, err := c.Get("https://google.com/")
if err != nil {
log.Fatalf("GET error: %v", err)
}

log.Printf("got %q", resp.Status)

编辑:如果您需要在连接实际发生之前设置选项,您可以在DialContext 中尝试这样做,但这是相当不可移植、不安全、不考虑上下文,并且可能迟早会崩溃:

tcpAddr, err := net.ResolveTCPAddr(network, addr)
if err != nil {
return nil, err
}

sa := &syscall.SockaddrInet4{
Port: tcpAddr.Port,
Addr: [4]byte{tcpAddr.IP[0], tcpAddr.IP[1], tcpAddr.IP[2], tcpAddr.IP[3]},
}

fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
if err != nil {
return nil, err
}

err = syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_TOS, 128)
if err != nil {
return nil, err
}

err = syscall.Connect(fd, sa)
if err != nil {
return nil, err
}

file := os.NewFile(uintptr(fd), "")
conn, err := net.FileConn(file)
if err != nil {
return nil, err
}

return conn, nil

编辑 2:在 Go 1.11 中,您将能够执行此操作:

dialer := &net.Dialer{
Control: func(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TOS, 128)
if err != nil {
log.Printf("control: %s", err)
return
}
})
},
}
// ...
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: dialer.DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}

关于http - 如何用go语言为http客户端设置套接​​字选项(IP_TOS)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40544096/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com