go - 如何在 golang 中的单个 TCP 连接上并发写入和读取?

标签 go mutex tcpclient

我尝试创建一个用于同时进行多个写入和读取的单一 TCP 连接客户端。例如,TCP 服务器将像您编写的那样返回值。 问题是写入和读取之间交换的数据。我已尝试使用 sync.Mutex,但它仍然不起作用。

我的结果是:

2018/03/10 12:52:10 STRING 4:1
2018/03/10 12:52:10 STRING 5:6
2018/03/10 12:52:10 STRING 2:3
and so on

我的期望是:

2018/03/10 12:52:10 STRING 4:4
2018/03/10 12:52:10 STRING 5:5
2018/03/10 12:52:10 STRING 2:2
2018/03/10 12:52:10 STRING 3:3

这是我的代码: 包主

import (
    "bufio"
    "log"
    "net"
    "strconv"
    "sync"
    "time"
)

type Cc struct {
    mux sync.Mutex
    rw  *bufio.ReadWriter
}

func main() {
    addr := "127.0.0.1:3333"
    log.Println("Dial " + addr)
    conn, err := net.Dial("tcp", addr)
    cc := Cc{
        rw: bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)),
    }

    if err != nil {
        log.Println(err)
    }
    for i := 1; i <= 10; i++ {
        go testC(cc, strconv.Itoa(i))
    }

    time.Sleep(60 * time.Second)

}

func testC(cc Cc, st string) {
    cc.mux.Lock()
    defer cc.mux.Unlock()
    _, err := cc.rw.WriteString(st + "\n")
    if err != nil {
        log.Println(err)
        // return errors.Wrap(err, "Could not send additional STRING data ("+strconv.Itoa(n)+" bytes written)")
    }
    // log.Println("Flush the buffer."s)
    err = cc.rw.Flush()
    if err != nil {
        log.Println(err)
        // return errors.Wrap(err, "Flush failed.")
    }

    time.Sleep(3 * time.Second)

    // Read the reply.
    // log.Println("Read the reply.")
    response, err := cc.rw.ReadString('\n')
    if err != nil {
        log.Println(err)
        // return errors.Wrap(err, "Client: Failed to read the reply: '"+response+"'")
    }

    log.Println("STRING " + st + ":" + response)
    // cc.mux.Unlock()
}

抱歉我的英语不好,谢谢。

最佳答案

func testC(cc Cc, st string) 实际上获取了 cc 的副本。因此,即使锁定互斥量,您实际上也锁定了它的 10 个完全独立的副本。因此,您的锁定代码无效。

尝试将 testC 函数签名更改为 func testC(cc *Cc, st string)。然后你调用 go testC(&cc, strconv.Itoa(i))

关于go - 如何在 golang 中的单个 TCP 连接上并发写入和读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49205958/

相关文章:

C# TcpClient发送数据后关闭XNA游戏窗口

Golang 容器/列表创建 FindAll 函数

http - 自签名代理客户端

go - 如何在golang中将字节附加到字节数组?不是字节数组到字节数组 slice 等

c++ - 槽中的 QMutex

c# - 无法建立连接,因为目标机器主动拒绝它 - 使用 Socket 或 TcpClient

multithreading - 如果我的程序有更多线程,它会获得更多的 CPU 时间吗

c++ - 如何最好地测试 Mutex 实现?

multithreading - 互斥体与信号量中的优先级反转

java - socket.shutdownOutput() 的目的