我在TCP
的{{1}}上遇到了一些文件传输问题。文件传输有时会起作用,有时会卡在中间。当它卡住时,它看起来好像在期望通信通道中的数据但是没有数据也没有错误。因此它无限期地被卡住了。为了让事情变得混乱,它显示了同一文件的这种行为,即对于同一文件,它有时会起作用,有时它不起作用。
这是我的程序的工作方式。它会监听传入的请求。请求采用go
格式。根据请求类型,它将执行不同的操作。我发布了与文件传输相关的代码段。
server.go
JSON
test.go
package main
import (
"bufio"
"encoding/json"
"fmt"
_"io"
"net"
"os"
)
const (
COMMAND_RECEIVE_FILE = "TRANSFER_FILE"
COMMAND_EXIT = "EXIT"
CONNECTION_TYPE = "tcp"
CONNECTION_PORT = "3645"
CONNECTION_HOST = ""
BUFFER_SIZE = 1024
)
type Command struct {
Identifier string `json:"identifier"`
Name string `json:"name"`
Size int64 `json:"size"`
}
type Result struct {
Message string `json:"message"`
}
func receiveFile(connection net.Conn, fileName string, fileSize int64) Result {
fmt.Println("Receiving file")
result := Result{Message: ""}
file, err := os.Create(fileName)
if err != nil {
fmt.Println(err)
result.Message = "Error opening file: " + fileName
return result
}
defer file.Close()
fileBuffer := make([]byte, BUFFER_SIZE)
bytesRead := int64(0)
count := 0
for {
if fileSize-bytesRead < int64(BUFFER_SIZE) {
fileBuffer = make([]byte, fileSize-bytesRead)
}
fmt.Println("Reading ", BUFFER_SIZE, " bytes of data")
n, err := connection.Read(fileBuffer)
count++
fmt.Println("Completed reading", n, " bytes of data, count=", count)
file.Write(fileBuffer[0:n])
bytesRead += int64(n)
if err != nil {
result.Message = "File transfer incomplete"
break
}
if bytesRead >= fileSize {
result.Message = "File transfer complete"
break
}
}
file.Chmod(0777)
return result
}
func main() {
ln, err := net.Listen(CONNECTION_TYPE, CONNECTION_HOST + ":"+CONNECTION_PORT)
if err != nil {
fmt.Println("error opening a tcp connection")
}
for {
fmt.Println("waiting for new connection")
conn, err := ln.Accept()
if err != nil {
} else {
var commandStr string
reader := bufio.NewReader(conn)
var exitStatus = 1
for exitStatus == 1 {
fmt.Println("Waiting for new command: ")
line,_,err := reader.ReadLine()
if err != nil {
conn.Close()
exitStatus = 0
break
} else {
fmt.Println("Size read :", len(line))
}
commandStr = string(line)
fmt.Println("CommandStr: ", commandStr)
var msg Command
err = json.Unmarshal([]byte(commandStr), &msg)
if err != nil {
fmt.Println("Error")
conn.Close()
break
}
result := Result{}
fmt.Println("Received new command: ", msg.Identifier)
switch msg.Identifier {
case COMMAND_RECEIVE_FILE:
result = receiveFile(conn, msg.Name, msg.Size)
case COMMAND_EXIT:
exitStatus = 0
conn.Close()
default:
result = Result{Message: "Unrecognized command"}
}
out, _ := json.Marshal(result)
fmt.Fprint(conn, string(out)+"\n")
}
}
}
}
我在Linux和Windows上测试过,它在两个系统上都表现出相同的行为。我唯一能想到的是发送器比接收器更快,即使我在同一台机器上运行它。如果是这种情况,除了握手机制之外,解决它的最佳做法是什么。
答案 0 :(得分:2)
您无法将net.Conn
包裹在bufio.Reader
中,然后继续使用net.Conn
。您的功能被阻止的原因是您将数据保留在reader
中,因此您将无法达到所需的邮件大小。
您需要将reader
传递给receiveFile
函数,以免丢失缓冲数据。
您也忽略了isPrefix
的{{1}}返回值。如果您不打算处理该方法的所有情况,我会按照文档使用ReadLine
。