如何在golang中通知TCP客户端文件的结束?

huangapple go评论88阅读模式
英文:

how to notify TCP client the end of the file in golang?

问题

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

c 是连接的 *net.TCPConn

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

客户端代码如下:

与上述相同c 是连接的 *net.TCPConn

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

我的问题是:用这种方式,客户端无法接收到文件的EOF,所以io.Copy被阻塞。我必须调用c.CloseWrite来通知客户端文件已经结束。
如果我想发送文件,这种方法行不通,我该如何解决?

英文:

I want to send a file through TCP in golang.
here's my server code:

    c is connected *net.TCPConn
 
    file, _ := os.Open(fn)
    defer file.Close()
    io.Copy(c, file)
    // c.CloseWrite()

and client:

    as above, c is connected *net.TCPConn

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

my question is: in this way, the client can not receive the EOF of the file

so, io.Copy blocked. I have to call c.CloseWrite to notify client that the file is over.

If I want to send files, this will not work, How can I solve this?

答案1

得分: 6

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

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

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

英文:

If you are using a TCP connection, then os.EOF error means that the connection closed by the other end.

I think the only way to reliably send a file would be to implement a multi-state protocol.

Eg. At the first state of the transfer, tell the client how much bytes to read and go to state 2. In state 2, if all bytes are read, then we know that it read the whole file. If os.EOF is detected before all bytes are read, discard and start again.

答案2

得分: 2

在正常的C语言中,人们会使用shutdown(fd, SHUT_WR)来关闭TCP连接,以向另一方指示EOF。在Go语言中,您也可以这样做:

func shutdownWrite(conn net.Conn) {
     // 匿名接口。也可以明确使用TCP。
     if  v, ok := conn.(interface{ CloseWrite() error }); ok {
         v.CloseWrite()
     }
 }

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

英文:

In normal C, one would shutdown(fd, SHUT_WR) the TCP connection to indicate EOF to the other side. You can do this in go as well:

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

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

答案3

得分: 0

一切正常,如果你从发送方关闭连接的话。我现在做了同样的事情 - 通过TCP进行文件传输。如果在打开连接后添加

defer conn.Close()

一切都正常工作。例如:

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

Everything works, if you close the connection from the sender's side.
I made the same thing now - file transfer through TCP. Everything works fine if you add

defer conn.Close()

after opening the connection.
For example:

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

huangapple
  • 本文由 发表于 2012年11月1日 18:26:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/13175102.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定