From f490e9e3dbb26e1bfa3d748e02d3a5194b4b3192 Mon Sep 17 00:00:00 2001 From: godo Date: Tue, 10 Sep 2024 09:13:06 +0800 Subject: [PATCH] change sendfile --- godo/localchat/file.go | 47 +++++++++++++----- godo/localchat/server.go | 100 ++++++++++++++++++++------------------- 2 files changed, 86 insertions(+), 61 deletions(-) diff --git a/godo/localchat/file.go b/godo/localchat/file.go index 61684f4..b90e762 100644 --- a/godo/localchat/file.go +++ b/godo/localchat/file.go @@ -35,12 +35,13 @@ import ( "os" "path/filepath" "strconv" + "strings" "sync" "time" ) const ( - GlobalfileSize = 512 // 每个数据包的大小 + GlobalfileSize = 768 // 每个数据包的大小 ) type FileChunk struct { @@ -176,13 +177,12 @@ func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message Ud go func(index int) { defer wg.Done() idStr := message.Type + "@" + message.Hostname + "@" + filepath.Base(file.Name()) + "@" + fmt.Sprintf("%d", fSize) + "@" - fileLen := GlobalfileSize - len(idStr) - chunkData := make([]byte, fileLen) + //fileLen := GlobalfileSize - len(idStr) + chunkData := make([]byte, GlobalfileSize) n, err := file.Read(chunkData[:]) if err != nil && err != io.EOF { log.Fatalf("Failed to read file chunk: %v", err) } - //sendData(message, toIp) sendBinaryData(idStr, chunkData[:n], toIp) fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp) }(i) @@ -214,11 +214,16 @@ func sendBinaryData(idStr string, data []byte, toIp string) { log.Printf("Failed to write data: %v", err) } } + +var fileLocks = make(map[string]*sync.Mutex) + func ReceiveFiles(parts []string) (string, error) { - //fileType := parts[0] fileName := parts[2] - fileSize, _ := strconv.ParseInt(parts[3], 10, 64) - fileContent := []byte(parts[4]) + fileSize, err := strconv.ParseInt(parts[3], 10, 64) + if err != nil { + return "", fmt.Errorf("failed to parse file size: %v", err) + } + // 创建接收文件的目录 baseDir, err := libs.GetOsDir() if err != nil { @@ -235,6 +240,7 @@ func ReceiveFiles(parts []string) (string, error) { return "", fmt.Errorf("failed to create receive directory") } } + // 确定文件路径 filePath := filepath.Join(receiveDir, fileName) @@ -247,20 +253,36 @@ func ReceiveFiles(parts []string) (string, error) { } defer file.Close() } + + // 锁定文件 + lock, ok := fileLocks[fileName] + if !ok { + lock = &sync.Mutex{} + fileLocks[fileName] = lock + } + lock.Lock() + defer lock.Unlock() + file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Printf("Failed to open file: %v", err) return "", fmt.Errorf("failed to open file") } defer file.Close() - // 写入数据 - n, err := file.Write(fileContent) + + // 提取实际数据 + data := strings.Join(parts[4:], "") + if len(data) < 1 { + return "", fmt.Errorf("empty data") + } + + n, err := file.Write([]byte(data)) if err != nil { log.Printf("Failed to write data to file: %v", err) return "", fmt.Errorf("failed to write data to file") } - if n != len(fileContent) { - log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(fileContent)) + if n != len(data) { + log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(data)) return "", fmt.Errorf("incomplete write") } @@ -269,11 +291,12 @@ func ReceiveFiles(parts []string) (string, error) { log.Printf("Failed to stat file: %v", err) return "", fmt.Errorf("failed to stat file") } + if fileInfo.Size() == fileSize { fmt.Println("文件接收完成且大小一致") return filePath, nil } else { - fmt.Println("文件大小不一致") + fmt.Printf("文件大小不一致,发送大小为%d,接收大小为%d\n", fileSize, fileInfo.Size()) return "", fmt.Errorf("file size mismatch") } } diff --git a/godo/localchat/server.go b/godo/localchat/server.go index 4c9e489..bdb9e4d 100644 --- a/godo/localchat/server.go +++ b/godo/localchat/server.go @@ -94,61 +94,63 @@ func UdpServer() { log.Printf("Received UDP packet from %v: %s", remoteAddr, buffer[:n]) // 从 remoteAddr 获取 IP 地址 - if udpAddr, ok := remoteAddr.(*net.UDPAddr); ok { - ip := udpAddr.IP.String() - - parts := strings.Split(string(buffer[:n]), "@") // 假设标识符不会超过256字节 - if parts[0] == "file" || parts[0] == "image" { - filename, err := ReceiveFiles(parts) - if err != nil { - log.Printf("error receiving file: %v", err) - continue - } - msg := UdpMessage{ - Hostname: parts[1], - Type: "fileAccessed", - Time: time.Now(), - IP: ip, - Message: filename, - } - AddMessage(msg) - continue - } - // 解析 UDP 数据 - var udpMsg UdpMessage - err = json.Unmarshal(buffer[:n], &udpMsg) + udpAddr, ok := remoteAddr.(*net.UDPAddr) + if !ok { + log.Printf("unexpected address type: %T", remoteAddr) + continue + } + ip := udpAddr.IP.String() + + parts := strings.Split(string(buffer[:n]), "@") // 假设标识符不会超过256字节 + if len(parts) >= 5 { + filename, err := ReceiveFiles(parts) if err != nil { - log.Printf("error unmarshalling UDP message: %v", err) + log.Printf("error receiving file: %v", err) continue } - udpMsg.IP = ip - - if udpMsg.Type == "heartbeat" { - UpdateUserStatus(udpMsg.IP, udpMsg.Hostname) - continue + msg := UdpMessage{ + Hostname: parts[1], + Type: parts[0], + Time: time.Now(), + IP: ip, + Message: filename, } + AddMessage(msg) + continue + } + // 解析 UDP 数据 + var udpMsg UdpMessage + err = json.Unmarshal(buffer[:n], &udpMsg) + if err != nil { + log.Printf("error unmarshalling UDP message: %v", err) + continue + } + udpMsg.IP = ip - // if udpMsg.Type == "file" { - // ReceiveFile(udpMsg) - // continue - // } - if udpMsg.Type == "fileAccessed" { - HandlerSendFile(udpMsg) - continue - } - // if udpMsg.Type == "image" { - // filePath, err := ReceiveFile(udpMsg) - // if err != nil { - // log.Printf("error receiving image: %v", err) - // continue - // } - // udpMsg.Message = filePath - // } - // 添加消息到 UserMessages - AddMessage(udpMsg) - } else { - log.Printf("unexpected address type: %T", remoteAddr) + if udpMsg.Type == "heartbeat" { + UpdateUserStatus(udpMsg.IP, udpMsg.Hostname) + continue } + + // if udpMsg.Type == "file" { + // ReceiveFile(udpMsg) + // continue + // } + if udpMsg.Type == "fileAccessed" { + HandlerSendFile(udpMsg) + continue + } + // if udpMsg.Type == "image" { + // filePath, err := ReceiveFile(udpMsg) + // if err != nil { + // log.Printf("error receiving image: %v", err) + // continue + // } + // udpMsg.Message = filePath + // } + // 添加消息到 UserMessages + AddMessage(udpMsg) + } }