【问题标题】:golang connection does not write until i close the connection or exit my client app在我关闭连接或退出我的客户端应用程序之前,golang 连接不会写入
【发布时间】:2020-04-19 21:23:03
【问题描述】:

我是 golang 的新手,我正在尝试在 go 中构建一个简单的 TCP 服务器和客户端。 客户端向服务器发送消息“来自客户端的问候”,并等待服务器响应 消息“已成功处理”。问题是客户端在我调用 conn.Close() 或在客户端上按 CTRL+C 之前不会刷新数据,如果我按 CTRL+C 或关闭连接,客户端将退出但不等待服务器的消息。服务器卡在这一行

n, copyErr := io.Copy(temp, conn)

有人可以帮我解决这个问题吗?

client.go

package main

import (
    "fmt"
    "io/ioutil"
    "net"
)

func writeMessage(conn net.Conn) {
    msg := "Hello from Client"
    _, writeErr := conn.Write([]byte(msg))
    if writeErr != nil {
        fmt.Println("Write error", writeErr)
    }


}

func main() {
    conn, err := net.Dial("tcp", "127.0.0.1:8080")
    if err != nil {
        fmt.Println("Dial error", err)
    }
    writeMessage(conn)

    msg, err := ioutil.ReadAll(conn)
    fmt.Println("Received message", string(msg), "from", conn.RemoteAddr())
}

server.go

package main

import (
    "bytes"
    "fmt"
    "io"
    "net"
    "os"
)

func handleConn(conn net.Conn) {
    localAddr := conn.LocalAddr()
    fmt.Println("Handling connection for", localAddr)

    temp := new(bytes.Buffer)
    n, copyErr := io.Copy(temp, conn)

    if copyErr != nil {
        fmt.Println("Copy error:", copyErr)
    }

    fmt.Println("Processed", n, "bytes")
    conn.Write([]byte("Successfully processed"))

}

func main() {
    ln, err := net.Listen("tcp", ":8080")
    if err != nil {
        fmt.Println("Error creating TCP server")
        os.Exit(1)
    }

    fmt.Println("Listening on port :8080")

    for {
        conn, err := ln.Accept()
        if err != nil {
            fmt.Println("Connection error")
        }
        handleConn(conn)
    }

}

【问题讨论】:

    标签: go tcp


    【解决方案1】:

    代码卡在n, copyErr := io.Copy(temp, conn) 上,因为在传入连接关闭之前它不会收到EOF(通过调用Close() 或关闭程序)。在您的情况下,您只想关闭连接的写入端。为此,TCPConn 实现了CloseWrite 方法。这是一个例子,你可以如何使用它:

    func writeMessage(conn net.Conn) error {
        if  cw, ok := conn.(interface{ CloseWrite() error }); ok {
            defer cw.CloseWrite()
        } else {
            return fmt.Errorf("Connection doesn't implement CloseWrite method")
        }
    
        msg := "Hello from Client"
        _, writeErr := conn.Write([]byte(msg))
        if writeErr != nil {
            fmt.Println("Write error", writeErr)
        }
    
        return nil
    }
    

    【讨论】:

    • 谢谢:+1 成功了!但是有更清洁的方法吗?
    • @Shubhangb 不是我知道或现在能想到的)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    相关资源
    最近更新 更多