【发布时间】:2020-10-31 16:50:24
【问题描述】:
我是 go lang 新手,在 go 中编写 tcp 代码时遇到问题。
这是我的代码
// client
package main
import (
"log"
"net"
"os"
"io"
"fmt"
)
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:4000")
if err != nil {
log.Fatal(err)
}
GetFileFromServer(conn, "test.txt")
}
func GetFileFromServer(conn net.Conn, fileName string) {
file, err := os.Create(fileName)
if err != nil {
log.Fatal(err)
return
}
defer file.Close()
conn.Write([]byte("get:" + fileName))
_, err = io.Copy(file, conn) // **IT DOES NOT STOP!!**
if err != nil {
log.Fatal(err)
return
}
fmt.Println("GET DONE")
}
// server
package main
import (
"bytes"
"log"
"net"
"io"
"fmt"
"strings"
"os"
)
const BUFFER_SIZE = 1024
const DIR_PATH = "./serverFile"
func main() {
listen, err := net.Listen("tcp", "127.0.0.1:4000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listen.Accept()
if err != nil {
log.Fatal(err)
}
defer conn.Close()
go ConnHandle(conn)
}
}
func ConnHandle(conn net.Conn) {
buffer := make([]byte, BUFFER_SIZE)
_, err := conn.Read(buffer)
if err != nil {
log.Fatal(err)
}
trimedBuffer := bytes.Trim(buffer, "\x00")
command := strings.Split(string(trimedBuffer), ":")
if command[0] == "get" {
PutFileToClient(conn, command[1])
return
}
}
func PutFileToClient(conn net.Conn, fileName string) {
file, err := os.Open(DIR_PATH + "\\" + fileName)
if err != nil {
log.Fatal(err)
return
}
defer file.Close()
_, err = io.Copy(conn, file)
if err != nil {
log.Fatal(err)
return
}
fmt.Println("PUT DONE")
}
----我想要的----
- 服务器和客户端被执行,
- 客户端发送到服务器“get:test.txt”
- 服务器收到它
- 服务器向客户端发送文件
- 客户端收到并保存在文件中
- 终止客户端
我认为“客户端的 io.Copy”没有停止的原因是因为它一直试图从连接中读取数据。
如何修复或停止它?
【问题讨论】:
-
发送文件时关闭连接。不要使用 defer 来关闭连接,这只会在函数返回时起作用。关闭处理文件副本的 goroutine 中的连接。你可以在那里推迟关闭它。
-
您还需要解决让客户端知道是否存在服务器端错误的问题。文件打开失败;否则客户端不会注意到短读。
-
添加了关于如何添加文件大小标头以覆盖一些潜在的服务器端错误的建议。