用golang编写TCP代理,在测试时获取DATA RACE

时间:2018-10-07 08:57:29

标签: go

我尝试使用golang将请求转发到不公开的机器。 This是一个有用的答案。但是,当我使用--race对代码进行测试时,它会警告 DATA RACE ,并且测试失败。

下面是代码。数据竞争发生在Response的{​​{1}}函数中,其中调用了两个proxy.go。测试产生的消息如下。

是否可以将连接的读取器和写入器分开?编写代理的安全方法是什么?

谢谢!

main.go

io.Copy

proxy.go

package main

import (
    "fmt"
    "io"
    "net"
    "net/http"
)

func server() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Hello world!")
    })
    http.ListenAndServe("127.0.0.1:80", nil)
}

func main() {
    go server()
    ln := NewServer("127.0.0.1", 8000)
    if ln == nil {
        fmt.Println("port not available")
    } else {
        for {
            conn, err := ln.Accept()
            if err != nil {
                // handle error
            }
            go func() {
                helloServer, err := net.Dial("tcp", "127.0.0.1:80")
                if err != nil {
                    fmt.Println("Cannot connect to mock server!")
                }
                Response(conn, helloServer)
            }()
        }
    }
}

proxy_test.go

package main

import (
    "fmt"
    "io"
    "net"
    "sync"
)

// NewServer create a socket listening on a given address
func NewServer(address string, port int) net.Listener {
    ln, err := net.Listen("tcp", fmt.Sprintf("%s:%d", address, port))
    if err != nil {
        // handle error
        ln = nil
    }
    return ln
}

// Response to the request of server
func Response(conn net.Conn, provider io.ReadWriter) {
    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        io.Copy(conn, provider)
    }()
    io.Copy(provider, conn)
    wg.Wait()
    defer conn.Close()
}

下面是消息

运行package main import ( "bufio" "bytes" "fmt" "net" "testing" ) func GetServer(t *testing.T) (net.Listener, int) { server, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Errorf("Cannot listen on any port") } port := server.Addr().(*net.TCPAddr).Port return server, port } func TestResponse(t *testing.T) { server, port := GetServer(t) text := "Hello World\n" go func(t *testing.T) { for { conn, err := server.Accept() if err != nil { // handle error } go Response(conn, bytes.NewBufferString(text)) } }(t) conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port)) if err != nil { t.Errorf("Cannot connect to mock server!") } status, err := bufio.NewReader(conn).ReadString('\n') if err != nil || status != text { t.Errorf("Response method lost information! %s", status) } }

go test --race

运行C:\Users\lenovo\go\src\github.com\limjcst\proxy>go test --race ================== WARNING: DATA RACE Write at 0x00c042126060 by goroutine 10: bytes.(*Buffer).WriteTo() C:/Go/src/bytes/buffer.go:238 +0x63 io.copyBuffer() C:/Go/src/io/io.go:382 +0x49c io.Copy() C:/Go/src/io/io.go:362 +0x7b github.com/limjcst/proxy.Response.func1() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy.go:26 +0xe7 Previous write at 0x00c042126060 by goroutine 9: bytes.(*Buffer).ReadFrom() C:/Go/src/bytes/buffer.go:202 +0x50 io.copyBuffer() C:/Go/src/io/io.go:386 +0x41e io.Copy() C:/Go/src/io/io.go:362 +0x7b github.com/limjcst/proxy.Response() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy.go:28 +0x150 Goroutine 10 (running) created at: github.com/limjcst/proxy.Response() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy.go:24 +0xc8 Goroutine 9 (running) created at: github.com/limjcst/proxy.TestResponse.func1() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy_test.go:29 +0xb7 ================== ================== WARNING: DATA RACE Read at 0x00c042126000 by goroutine 10: bytes.(*Buffer).WriteTo() C:/Go/src/bytes/buffer.go:74 +0x78 io.copyBuffer() C:/Go/src/io/io.go:382 +0x49c io.Copy() C:/Go/src/io/io.go:362 +0x7b github.com/limjcst/proxy.Response.func1() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy.go:26 +0xe7 Previous write at 0x00c042126000 by goroutine 9: bytes.(*Buffer).grow() C:/Go/src/bytes/buffer.go:146 +0x23c bytes.(*Buffer).ReadFrom() C:/Go/src/bytes/buffer.go:204 +0x84 io.copyBuffer() C:/Go/src/io/io.go:386 +0x41e io.Copy() C:/Go/src/io/io.go:362 +0x7b github.com/limjcst/proxy.Response() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy.go:28 +0x150 Goroutine 10 (running) created at: github.com/limjcst/proxy.Response() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy.go:24 +0xc8 Goroutine 9 (running) created at: github.com/limjcst/proxy.TestResponse.func1() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy_test.go:29 +0xb7 ================== ================== WARNING: DATA RACE Read at 0x00c042126018 by goroutine 10: bytes.(*Buffer).WriteTo() C:/Go/src/bytes/buffer.go:74 +0x9b io.copyBuffer() C:/Go/src/io/io.go:382 +0x49c io.Copy() C:/Go/src/io/io.go:362 +0x7b github.com/limjcst/proxy.Response.func1() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy.go:26 +0xe7 Previous write at 0x00c042126018 by goroutine 9: bytes.(*Buffer).grow() C:/Go/src/bytes/buffer.go:149 +0x27d bytes.(*Buffer).ReadFrom() C:/Go/src/bytes/buffer.go:204 +0x84 io.copyBuffer() C:/Go/src/io/io.go:386 +0x41e io.Copy() C:/Go/src/io/io.go:362 +0x7b github.com/limjcst/proxy.Response() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy.go:28 +0x150 Goroutine 10 (running) created at: github.com/limjcst/proxy.Response() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy.go:24 +0xc8 Goroutine 9 (running) created at: github.com/limjcst/proxy.TestResponse.func1() C:/Users/lenovo/go/src/github.com/limjcst/proxy/proxy_test.go:29 +0xb7 ================== --- FAIL: TestResponse (0.15s) testing.go:730: race detected during execution of test FAIL exit status 1 FAIL github.com/limjcst/proxy 0.226s

go env

运行C:\Users\lenovo\go\src\github.com\limjcst\proxy>go env set GOARCH=amd64 set GOBIN= set GOCACHE=C:\Users\lenovo\AppData\Local\go-build set GOEXE=.exe set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOOS=windows set GOPATH=C:\Users\lenovo\go set GORACE= set GOROOT=C:\Go set GOTMPDIR= set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64 set GCCGO=gccgo set CC=gcc set CXX=g++ set CGO_ENABLED=1 set CGO_CFLAGS=-g -O2 set CGO_CPPFLAGS= set CGO_CXXFLAGS=-g -O2 set CGO_FFLAGS=-g -O2 set CGO_LDFLAGS=-g -O2 set PKG_CONFIG=pkg-config set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\lenovo\AppData\Local\Temp\go-build632729010=/tmp/go-build -gno-record-gcc-switches

go version

0 个答案:

没有答案