2016-11-11 7 views
2

私は言語に行く初心者です。 httpクライアント/サーバーを開発するためにgo言語を使用する予定です。私はパッケージ でソケットオプションを設定する方法を見つけていないHTTPクライアントパッケージでサポートされる機能のリストを閲覧しながら は(私はそれを使用する方法がわからないこともあります)。私は、httpクライアント接続を呼び出す前に、fdにDSCPオプション(IP_TOS)を設定する必要があります。 (ソケットオプションを設定するsyscallオプションがありますが、httpパッケージからfdを取得する方法はありません)。HTTPクライアントのソケットオプション(IP_TOS)をgo言語で設定するには?

httpサーバー側では、ソケットオプション(IP_TOS)を設定できます。 コードの抜粋:HTTPクライアント側で

 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) 

ソケット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) 

ありがとうございます!

答えて

2

あなたがあなた自身の*http.Clientの独自のhttp.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.SOL_SOCKET, 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) 

をEDIT:あなたは、接続が実際に起こる前にオプションを設定する必要がある場合は、することができます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.SOL_SOCKET, 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 
+0

お返事ありがとうございました。上記のコードをサンプルプログラムでテストしましたが、ソケットオプションIP_TOSの値は、httpクライアントから開始されたsynパケットに設定できませんでした。ここでは、DialContext(ctx、network、addr)に引数を渡しながら、ctxとして渡すコンテキストを作成する方法について疑いがあります。現在私は** DialContext(context.Background()ネットワーク、addr)**を使用していましたか? –

+0

@ManojSaha編集して試してみてください。動作しているかどうかに関係なく、Go発行トラッカーの機能を要求して、何らかの形でFDの設定オプションを許可したい場合があります。 –

+0

あなたの努力のおかげで再び!私はサンプルプログラムでテストしましたが、dscpの設定が成功したためapiを設定し、dscpのget apiを使ってdscp値を読むことができましたが、synパケットのtcp接続要求に反映されません。それでも私はdscpが0であると思っています。 –

関連する問題