Golang中net/http Accept()在Linux上阻塞整个程序的问题探讨

Golang中net/http Accept()在Linux上阻塞整个程序的问题探讨 你好! 😊
我目前正在开发一个我分叉的开源项目
( https://github.com/sagneta/go-rtsengine )
但来自 GitHub 的代码在以下代码段处停止运行:

listener, err := net.Listen("tcp", "localhost:8082")
if err != nil {
return err
}
fmt.Printf("1") //Prints 1
conn, err := listener.Accept()
fmt.Printf("2") //Never prints 2

我是 Go 语言的新手,对此感到非常困惑,现在该怎么办。我是应该更换标准库,还是降级 Go 版本?
我当前的版本是 go1.10.2 linux/amd64,使用的是 Manjaro Linux。
非常感谢任何帮助!


更多关于Golang中net/http Accept()在Linux上阻塞整个程序的问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

非常感谢! 这确实很愚蠢,但如果没有你的帮助,我可能会一直卡在那里 😊

更多关于Golang中net/http Accept()在Linux上阻塞整个程序的问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


好的,listener.Accept() 会一直等待,直到在 8082 端口有传入的 TCP 连接。

因此,连接到该端口,你的程序就会继续执行。

favicon.ico

net package - net - Go Packages

Package net provides a portable interface for network I/O, including TCP/IP, UDP, domain name resolution, and Unix domain sockets.

type Listener interface {
        // Accept waits for and returns the next connection to the listener.
        Accept() (Conn, error)
        // [...]
}

这是一个常见的网络编程问题,主要原因是Accept()方法在没有客户端连接时会阻塞当前goroutine。在Go语言中,这通常不会"阻塞整个程序",但会阻塞当前goroutine的执行流程。

问题分析:

  • fmt.Printf("1") 正常输出,说明net.Listen成功
  • fmt.Printf("2") 没有输出,说明程序在listener.Accept()处阻塞等待客户端连接

解决方案是使用goroutine来处理连接接受,或者在实际使用场景中确保有客户端连接到指定端口。

示例代码:

package main

import (
    "fmt"
    "net"
    "time"
)

func main() {
    listener, err := net.Listen("tcp", "localhost:8082")
    if err != nil {
        fmt.Printf("Listen error: %v\n", err)
        return
    }
    fmt.Printf("1 - Server started on localhost:8082\n")

    // 方案1: 使用goroutine异步接受连接
    go func() {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Printf("Accept error: %v\n", err)
            return
        }
        fmt.Printf("2 - Connection accepted from: %v\n", conn.RemoteAddr())
        conn.Close()
    }()

    // 保持主程序运行
    time.Sleep(10 * time.Second)
    fmt.Println("Server shutting down")
}

或者使用一个完整的服务器示例:

package main

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

func handleConnection(conn net.Conn) {
    defer conn.Close()
    fmt.Printf("Handling connection from: %v\n", conn.RemoteAddr())
    
    // 简单的echo服务器
    io.Copy(conn, conn)
}

func main() {
    listener, err := net.Listen("tcp", "localhost:8082")
    if err != nil {
        fmt.Printf("Listen error: %v\n", err)
        return
    }
    defer listener.Close()
    
    fmt.Printf("Server listening on localhost:8082\n")

    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Printf("Accept error: %v\n", err)
            continue
        }
        fmt.Printf("Accepted connection from: %v\n", conn.RemoteAddr())
        
        go handleConnection(conn)
    }
}

要测试这个服务器,可以在另一个终端使用telnet或nc连接:

telnet localhost 8082
# 或者
nc localhost 8082

关于版本问题:Go 1.10.2确实比较旧,建议升级到更新的稳定版本(如Go 1.21+),但这个问题与Go版本无关,是网络编程的正常行为。标准库net/http不需要更换,这是正确的使用方式。

回到顶部