创建服务器并连接到它

ninesalt:

我正在尝试创建一个服务器并在Go中连接到它,但是当服务器开始运行时,它后面的任何函数都不会被调用,因为启动服务器的函数似乎正在阻塞。我尝试使用goroutine在后台运行服务器,以便可以执行其他代码,但这也不起作用。我收到我不明白的错误

紧急情况:运行时错误:无效的内存地址或nil指针取消引用[信号SIGSEGV:分段违规代码= 0x1 addr = 0x18 pc = 0x496757]

这是我的服务器代码

func RunServer(port string) {

    fmt.Println("Launching server...")
    ln, err := net.Listen("tcp", port)
    conn, _ := ln.Accept()

    // run loop forever (or until ctrl-c)
    for {

        // will listen for message to process ending in newline (\n)
        message, _ := bufio.NewReader(conn).ReadString('\n')

        // output message received
        fmt.Print("Message Received:", string(message))

        // sample process for string received
        newmessage := strings.ToUpper(message)

        // send new string back to client
        conn.Write([]byte(newmessage + "\n"))
    }
}

这是客户端的代码。

func createInitalClient(port int) {

    // run server then create a client that connects to it
    portToRunOn := fmt.Sprintf("%s%d", ":", port)
    go RunServer(portToRunOn)
}

func main() {

    createInitalClient(5000)

    // connect to this socket
    conn, _ := net.Dial("tcp", "127.0.0.1:5000")

    for {
        // read in input from stdin

        reader := bufio.NewReader(os.Stdin)
        fmt.Print("Text to send: ")
        text, _ := reader.ReadString('\n')

        // send to socket
        fmt.Fprintf(conn, text+"\n")

        // listen for reply
        message, _ := bufio.NewReader(conn).ReadString('\n')
        fmt.Print("Message from server: " + message)
    }
}

我是在正确执行此操作,还是有其他方法可以执行我要执行的操作?我有点不愿使用goroutine,因为在我的情况下引入异步行为可能是错误的。

编辑1:似乎正在发生此错误,因为客户端试图在启动之前连接到服务器。

编辑2:我(可能)通过在服务器中添加一个布尔通道来修复此问题,该通道在听众开始接受连接之前返回true。然后,如果来自通道的值为true,则客户端仅连接到服务器。在这种情况下,我不确定这是否是正确的解决方法,但它似乎可以正常工作。

宇宙O骨:

您的服务器是在goroutine中启动的,该goroutine是由Go运行时异步生成的,将需要一些时间来计划和执行。具体来说,运行时不会在继续执行main功能之前等待服务器goroutine启动

您要么需要:

  • 当服务器准备好接受连接时,安排服务器goroutine进行通信–使用通道是可以接受的机制;要么
  • 让您的客户端连接尝试反复连接,直到接受连接为止–实际上是轮询服务器的就绪状态。例如:

    // Predeclare "conn" to ensure it remains in scope outside the loop
    var conn net.Conn
    
    for {
        var err error
        conn, err = net.Dial("tcp", "127.0.0.1:5000")
    
        // Failed connection, try again in a second.
        // TODO: limit the number of attempts before giving up.
        if err != nil {
            time.Sleep(time.Second)
            continue
        }
    
        // Connected successfully. Continue.
        break
    }
    
    // do something with "conn"
    

错误值

正如您对问题的评论所指出的那样,您的代码在多个地方都忽略了错误值。

请不要在实际的生产代码中执行此操作。返回错误是有原因的,并且可能表明代码外部存在问题,导致您的程序无法正确继续执行。您需要检查错误值,并在返回错误值时采取适当的措施。从函数调用返回的其他值,尤其是标准库中的任何值,如果返回error的不是,则不太可能有意义nil

是的,您最终会写if err != nil很多东西。这是预料之中的,在某些情况下可以采用多种模式来避免使代码看起来过于重复。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章