From cd287dc5f47e72ece6e68681c87101020b8ff869 Mon Sep 17 00:00:00 2001 From: godo Date: Tue, 10 Sep 2024 08:38:19 +0800 Subject: [PATCH] change msg --- godo/localchat/file.go | 104 ++++++++++----------------------------- godo/localchat/server.go | 57 ++++++++++++++------- 2 files changed, 65 insertions(+), 96 deletions(-) diff --git a/godo/localchat/file.go b/godo/localchat/file.go index 9bfb755..61684f4 100644 --- a/godo/localchat/file.go +++ b/godo/localchat/file.go @@ -24,7 +24,7 @@ package localchat import ( - "encoding/base64" + "encoding/binary" "encoding/json" "fmt" "godo/libs" @@ -34,12 +34,13 @@ import ( "net/http" "os" "path/filepath" + "strconv" "sync" "time" ) const ( - fileSize = 512 // 每个数据包的大小 + GlobalfileSize = 512 // 每个数据包的大小 ) type FileChunk struct { @@ -146,7 +147,7 @@ func handleFile(filePath string, toIp string, message UdpMessage) { fileSize := fileInfo.Size() // 计算需要发送的数据包数量 - numChunks := (fileSize + fileSize - 1) / fileSize + numChunks := (fileSize + GlobalfileSize - 1) / GlobalfileSize // 发送文件 SendFile(file, int(numChunks), toIp, fileSize, message) @@ -174,33 +175,22 @@ func SendFile(file *os.File, numChunks int, toIp string, fSize int64, message Ud wg.Add(1) go func(index int) { defer wg.Done() - - var chunkData [fileSize]byte + idStr := message.Type + "@" + message.Hostname + "@" + filepath.Base(file.Name()) + "@" + fmt.Sprintf("%d", fSize) + "@" + fileLen := GlobalfileSize - len(idStr) + chunkData := make([]byte, fileLen) n, err := file.Read(chunkData[:]) if err != nil && err != io.EOF { log.Fatalf("Failed to read file chunk: %v", err) } - // 创建文件块 - chunk := FileChunk{ - ChunkIndex: index, - Data: chunkData[:n], - Checksum: calculateChecksum(chunkData[:n]), - Timestamp: time.Now(), - Filename: filepath.Base(file.Name()), - Filesize: fSize, - } - - message.Message = chunk - sendData(message, toIp) - + //sendData(message, toIp) + sendBinaryData(idStr, chunkData[:n], toIp) fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp) }(i) } wg.Wait() } - -func sendData(message UdpMessage, toIp string) { +func sendBinaryData(idStr string, data []byte, toIp string) { port := "56780" addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%s", toIp, port)) if err != nil { @@ -213,30 +203,22 @@ func sendData(message UdpMessage, toIp string) { } defer conn.Close() - data, _ := json.Marshal(message) - _, err = conn.Write(data) + // 添加长度前缀 + identifier := []byte(idStr) + lengthPrefix := make([]byte, 4) + binary.BigEndian.PutUint32(lengthPrefix, uint32(len(data))) + + // 发送长度前缀和数据 + _, err = conn.Write(append(append(identifier, lengthPrefix...), data...)) if err != nil { log.Printf("Failed to write data: %v", err) } } -func ReceiveFile(msg UdpMessage) (string, error) { - messageMap, ok := msg.Message.(map[string]interface{}) - if !ok { - return "", fmt.Errorf("invalid message type: expected map[string]interface{}, got %T", msg.Message) - } - - // 从 map 中提取 FileChunk 字段 - chunk, err := extractFileChunkFromMap(messageMap) - if err != nil { - return "", err - } - - // calculatedChecksum := calculateChecksum(chunk.Data) - // if calculatedChecksum != chunk.Checksum { - // fmt.Printf("Checksum mismatch for chunk %d from %s\n", chunk.ChunkIndex, msg.IP) - // return "", fmt.Errorf("checksum mismatch") - // } - +func ReceiveFiles(parts []string) (string, error) { + //fileType := parts[0] + fileName := parts[2] + fileSize, _ := strconv.ParseInt(parts[3], 10, 64) + fileContent := []byte(parts[4]) // 创建接收文件的目录 baseDir, err := libs.GetOsDir() if err != nil { @@ -253,9 +235,8 @@ func ReceiveFile(msg UdpMessage) (string, error) { return "", fmt.Errorf("failed to create receive directory") } } - // 确定文件路径 - filePath := filepath.Join(receiveDir, chunk.Filename) + filePath := filepath.Join(receiveDir, fileName) // 如果文件不存在,则创建新文件 if _, err := os.Stat(filePath); os.IsNotExist(err) { @@ -266,23 +247,20 @@ func ReceiveFile(msg UdpMessage) (string, error) { } defer file.Close() } - - // 打开或追加到现有文件 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(chunk.Data) + n, err := file.Write(fileContent) 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(chunk.Data) { - log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(chunk.Data)) + if n != len(fileContent) { + log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(fileContent)) return "", fmt.Errorf("incomplete write") } @@ -291,7 +269,7 @@ func ReceiveFile(msg UdpMessage) (string, error) { log.Printf("Failed to stat file: %v", err) return "", fmt.Errorf("failed to stat file") } - if fileInfo.Size() == chunk.Filesize { + if fileInfo.Size() == fileSize { fmt.Println("文件接收完成且大小一致") return filePath, nil } else { @@ -299,31 +277,3 @@ func ReceiveFile(msg UdpMessage) (string, error) { return "", fmt.Errorf("file size mismatch") } } -func calculateChecksum(data []byte) uint32 { - checksum := uint32(0) - for _, b := range data { - checksum += uint32(b) - } - return checksum -} - -// 从 map 中提取 FileChunk 结构体 -func extractFileChunkFromMap(m map[string]interface{}) (FileChunk, error) { - chunk := FileChunk{} - - // 从 map 中提取字段 - chunk.ChunkIndex, _ = m["chunk_index"].(int) - dataStr, _ := m["data"].(string) - dataBytes, err := base64.StdEncoding.DecodeString(dataStr) - if err != nil { - return chunk, fmt.Errorf("failed to decode data: %v", err) - } - chunk.Data = dataBytes - chunk.Checksum, _ = m["checksum"].(uint32) - timestamp, _ := m["timestamp"].(string) - chunk.Timestamp, _ = time.Parse(time.RFC3339, timestamp) - chunk.Filename, _ = m["filename"].(string) - chunk.Filesize, _ = m["filesize"].(int64) - - return chunk, nil -} diff --git a/godo/localchat/server.go b/godo/localchat/server.go index f5233c3..4c9e489 100644 --- a/godo/localchat/server.go +++ b/godo/localchat/server.go @@ -28,6 +28,7 @@ import ( "godo/libs" "log" "net" + "strings" "time" ) @@ -92,16 +93,34 @@ func UdpServer() { } log.Printf("Received UDP packet from %v: %s", remoteAddr, buffer[:n]) - // 解析 UDP 数据 - var udpMsg UdpMessage - err = json.Unmarshal(buffer[:n], &udpMsg) - if err != nil { - log.Printf("error unmarshalling UDP message: %v", err) - continue - } // 从 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) + if err != nil { + log.Printf("error unmarshalling UDP message: %v", err) + continue + } udpMsg.IP = ip if udpMsg.Type == "heartbeat" { @@ -109,22 +128,22 @@ func UdpServer() { continue } - if udpMsg.Type == "file" { - ReceiveFile(udpMsg) - 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 - } + // 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 {