英文:
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()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论