Golang模拟多路并发TCP服务器连接

Golang模拟多路并发TCP服务器连接 我需要测试一个TCP服务器是否能正确处理多个客户端连接。

是否可以使用goroutine像这样?

func SendMsg(msg string) {
    conn, _ := net.Dial("tcp", ":1123")
    conn.Write([]byte(msg))
    conn.Close()
}
for i := 0; i < 50; i++ {
    go SendMsg("test")
}

当我尝试类似这样的代码时,程序会发生panic。

此致

5 回复

什么 panic?

更多关于Golang模拟多路并发TCP服务器连接的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


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

Norbert 比我先说了:听起来你的连接是 nil,就像这里:https://play.golang.org/p/mJSIcJLDpTD。移除 return 就会引发 panic。

func main() {
    var conn net.Conn
    conn.Write([]byte("data"))
}

或许应该检查一下net.Dial返回的err,它被返回是有原因的…

// 代码示例
func main() {
    conn, err := net.Dial("tcp", "golang.org:80")
    if err != nil {
        // 处理错误
    }
    // 使用连接
}

在Go中模拟多路并发TCP服务器连接是可行的,但你的代码存在几个关键问题。主要问题是没有正确处理连接建立失败和并发同步。

以下是修复后的完整示例:

package main

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

func SendMsg(msg string, wg *sync.WaitGroup) {
    defer wg.Done()
    
    conn, err := net.Dial("tcp", "localhost:1123")
    if err != nil {
        fmt.Printf("连接失败: %v\n", err)
        return
    }
    defer conn.Close()
    
    _, err = conn.Write([]byte(msg))
    if err != nil {
        fmt.Printf("发送失败: %v\n", err)
        return
    }
    
    // 可选:读取服务器响应
    buffer := make([]byte, 1024)
    conn.SetReadDeadline(time.Now().Add(2 * time.Second))
    n, err := conn.Read(buffer)
    if err != nil {
        fmt.Printf("读取响应失败: %v\n", err)
        return
    }
    
    fmt.Printf("收到响应: %s\n", string(buffer[:n]))
}

func main() {
    var wg sync.WaitGroup
    
    for i := 0; i < 50; i++ {
        wg.Add(1)
        go SendMsg(fmt.Sprintf("test-%d", i), &wg)
    }
    
    wg.Wait()
    fmt.Println("所有客户端连接完成")
}

关键改进:

  1. 错误处理:必须检查net.Dialconn.Write的返回值
  2. 连接管理:使用defer conn.Close()确保连接正确关闭
  3. 并发同步:使用sync.WaitGroup等待所有goroutine完成
  4. 超时控制:为读取操作设置超时,避免阻塞

对应的简单TCP服务器示例:

package main

import (
    "fmt"
    "net"
)

func handleConnection(conn net.Conn) {
    defer conn.Close()
    
    buffer := make([]byte, 1024)
    n, err := conn.Read(buffer)
    if err != nil {
        fmt.Printf("读取错误: %v\n", err)
        return
    }
    
    msg := string(buffer[:n])
    fmt.Printf("收到消息: %s\n", msg)
    
    // 回显消息
    response := fmt.Sprintf("ECHO: %s", msg)
    conn.Write([]byte(response))
}

func main() {
    listener, err := net.Listen("tcp", ":1123")
    if err != nil {
        panic(err)
    }
    defer listener.Close()
    
    fmt.Println("服务器启动,监听端口 1123")
    
    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Printf("接受连接错误: %v\n", err)
            continue
        }
        
        go handleConnection(conn)
    }
}

这个实现能够正确处理50个并发客户端连接,每个连接发送消息并接收服务器响应。确保先启动服务器,再运行客户端测试代码。

回到顶部