客户端无法将数据发送到 golang 中的 TCP 服务器?

我有 TCP 服务器和客户端,简单 TCP 服务器将只接收传入数据并打印它,客户端将不断创建套接字连接并在循环中将数据发送到 TCP 服务器。


我得到的信息是,如果 TCP 连接正确关闭,这个过程应该继续进行而不会出现任何崩溃。


但是在从客户端接收到服务器的一些数据后,客户端因错误而崩溃


total times data send: 16373


panic: runtime error: invalid memory address or nil pointer dereference

[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x10d7594]


goroutine 1 [running]:

main.sendData()


/Users/apple/Desktop/Personal/umbrellaserver/src/tests/clinet.go:178 

+0xb4

main.main()


/Users/apple/Desktop/Personal/umbrellaserver/src/tests/clinet.go:170 

+0x2a

exit status 2

服务器.go


package main


import (

    "bufio"

    "fmt"

    "net"

    "sync"

)


var wg sync.WaitGroup

var count = 0

var timeX string = ""


var connQueue = make(chan string)


func main() {

    tcpListner := startTCPConnection()

    incomingTCPListener(tcpListner)

}


//startTCPConnection

func startTCPConnection() net.Listener {

    tcpListner, tcpConnectonError := net.Listen("tcp", "localhost:3000")

    if tcpConnectonError != nil {

        print(tcpConnectonError)

        return 

    }

    return tcpListner

}


//incomingTCPListener

func incomingTCPListener(tcpListner net.Listener) {


    for {

        incomingConnection, incomingConnectionError := tcpListner.Accept()

        if incomingConnectionError != nil {

            print(incomingConnectionError)

            return

        }

        wg.Add(1)

        go processIncomingRequest(incomingConnection)

        wg.Wait()

    }

}


//processIncomingRequest

func processIncomingRequest(connection net.Conn) {


    defer connection.Close()


    var scanner = bufio.NewScanner(connection)


    var blob = ""

    for scanner.Scan() {

        fmt.Println("sadd")

        text := scanner.Text()

        blob += text

    }

    print(blob)

    count++

    fmt.Println("totalCount", count)

    wg.Done()

}

有什么办法可以避免这种崩溃,让它一直运行下去吗? 我是 Go 的新手,所以如果我犯了任何愚蠢的错误,我很抱歉。



不负相思意
浏览 129回答 3
3回答

鸿蒙传说

首先,如果你想打印到 stderr,(即你的打印调用),我建议使用 fmt 库fmt.Fprintln(os.Stderr, "hello world")为什么:因为打印功能不能保证留在语言中。1个其次,通常的做法是将错误名称命名为err,而不必将错误拼写为tcpConnectionError.connection, connectionError := net.Dial("tcp", "localhost:3000")第三,由于您在服务器中使用 tcp,因此正在侦听 ipv6 和 ipv4。我至少在 Windows 机器上观察到连接打开两个连接,一个用于 ipv4 和 ipv6,然后丢弃 ipv6 连接以支持 ipv4。最后,当 TCP 连接关闭时,端口不能立即重新使用,因为操作系统必须等待 TIME_WAIT 间隔(最大段生存期,MSL)的持续时间。您的客户端代码正在打开大量非常短暂的 tcp 连接,并且根据您临时端口范围的范围,您的代码可能会或可能不会崩溃。从16373的数量来看,你有默认范围。2个>> sysctl net.inet.ip.portrange.first net.inet.ip.portrange.lastnet.inet.ip.portrange.first: 49152net.inet.ip.portrange.last: 65535最后,如果您想避免因端口用完而导致崩溃:1. 增加端口的临时范围2. 使用 Docker,容器在它们自己的网络上,因此使用一组不同的端口绕过有限的端口范围。3. 在您的客户端代码中引入一个自动收报机,以模拟每 x 秒/分钟的连接package mainimport (    "fmt"    "net"    "time")var count = 0func testJSON2() string {    return `Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32. The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.`}func main() {    max := 1000    timer1 := time.NewTicker(5 * time.Second)    i := 0    for range timer1.C {        sendData()        if i == max {            timer1.Stop()        }        i++    }}func sendData() {    connection, connectionError := net.Dial("tcp", "localhost:3000")    fmt.Println(connection.LocalAddr())    if connectionError != nil {        fmt.Println(connectionError)        return    }    newmessage := testJSON2()    connection.Write([]byte(newmessage + "\n"))    count++    fmt.Println(count)    err := connection.Close()    if err != nil {        fmt.Println(err)    }}

慕姐4208626

if connectionError != nil {        fmt.Println(connectionError)        return     }defer connection.Close()defer connection.Close() 应该在错误检查之后,因为连接变量可以是 nil incase 拨号返回时出现一些错误。

暮色呼如

package mainimport (    "bufio"    "fmt"    "net"    "sync")var wg sync.WaitGroupvar count = 0var timeX string = ""var connQueue = make(chan string)func main() {    tcpListner := startTCPConnection()    incomingTCPListener(tcpListner)    wg.Wait()}//startTCPConnectionfunc startTCPConnection() net.Listener {    tcpListner, tcpConnectonError := net.Listen("tcp", "localhost:3000")    if tcpConnectonError != nil {        print(tcpConnectonError)        // return         log.Fatal(tcpConnectonError)    }    return tcpListner}//incomingTCPListenerfunc incomingTCPListener(tcpListner net.Listener) {    for {        incomingConnection, incomingConnectionError := tcpListner.Accept()        if incomingConnectionError != nil {            print(incomingConnectionError)            return        }        wg.Add(1)        go processIncomingRequest(incomingConnection)        // wg.Wait()    }}//processIncomingRequestfunc processIncomingRequest(connection net.Conn) {    defer connection.Close()    var scanner = bufio.NewScanner(connection)    var blob = ""    for scanner.Scan() {        fmt.Println("sadd")        text := scanner.Text()        blob += text    }    print(blob)    count++    fmt.Println("totalCount", count)    wg.Done()}问题出在server.go。我的猜测是您通过在 incomingTCPListener() 函数中调用 wg.Wait() 而不是 main() 来耗尽端口。此外,在 startTCPConnection() 函数中直接返回将导致编译器错误。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go