【问题标题】:how to notify TCP client the end of the file in golang?如何在golang中通知TCP客户端文件的结尾?
【发布时间】:2012-11-01 10:26:05
【问题描述】:

我想在 golang 中通过 TCP 发送文件。 这是我的服务器代码:

    c is connected *net.TCPConn

    file, _ := os.Open(fn)
    defer file.Close()
    io.Copy(c, file)
    // c.CloseWrite()

和客户:

    as above, c is connected *net.TCPConn

    file, _ := os.Create("file.txt")
    defer file.Close()
    io.Copy(file, c)

我的问题是:这样,客户端无法接收到文件的EOF

所以,io.Copy 被屏蔽了。我必须打电话给c.CloseWrite 通知客户文件结束了。

如果我想发送文件,这将不起作用,我该如何解决?

【问题讨论】:

    标签: file networking tcp go


    【解决方案1】:

    如果你使用的是TCP连接,那么os.EOF错误意味着连接被另一端关闭。

    我认为可靠发送文件的唯一方法是实现多状态协议。

    例如。在传输的第一个状态,告诉客户端要读取多少字节并进入状态 2。在状态 2,如果读取了所有字节,那么我们知道它读取了整个文件。如果在读取所有字节之前检测到 os.EOF,则丢弃并重新开始。

    【讨论】:

    • 所以我必须使用c.Read,io.Copy在这里没用?
    • @dilfish,Allent 想问你的是:你的意思是你想向客户端发送文件但之后不终止 TCP 连接? 如果是,那么这是行不通的,因为 TCP 只是传输不透明的字节流,而解释它是客户端的任务。因此,您必须在 TCP 之上设计一个“应用程序级协议”。正如艾伦建议的那样,服务器可能首先指示它将发送多少字节,然后客户端读取这些字节,将它们写入文件并等待其他“传输指示符”或其他什么。
    • 谢谢,我的问题是,io.Copy 不适合这种情况吗?好像不是,不是。
    • 正确,使用 TCP 连接时需要使用 net 包中的函数。我认为即使您在之后关闭连接,您仍然需要某种应用程序级协议,以防连接过早关闭。
    【解决方案2】:

    在正常的 C 中,一个人会关闭(fd,SHUT_WR)TCP 连接以向另一端指示 EOF。你也可以在 go 中这样做:

    func shutdownWrite(conn net.Conn) {
         // anonymous interface. Could explicitly use TCP instead.
         if  v, ok := conn.(interface{ CloseWrite() error }); ok {
             v.CloseWrite()
         }
     }
    

    https://golang.org/src/net/tcpsock_posix.go?s=2073:2109#L75

    【讨论】:

      【解决方案3】:

      如果您从发送方关闭连接,一切正常。
      我现在做了同样的事情——通过 TCP 传输文件。如果添加

      ,一切正常
      defer conn.Close()
      

      打开连接后。
      例如:

      conn, err := net.Dial("tcp", client)
      defer conn.Close()
      

      【讨论】:

        猜你喜欢
        • 2014-06-02
        • 2014-12-06
        • 2012-03-30
        • 1970-01-01
        • 2017-09-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多