Browse Source

change msg

master
godo 9 months ago
parent
commit
cd287dc5f4
  1. 104
      godo/localchat/file.go
  2. 57
      godo/localchat/server.go

104
godo/localchat/file.go

@ -24,7 +24,7 @@
package localchat package localchat
import ( import (
"encoding/base64" "encoding/binary"
"encoding/json" "encoding/json"
"fmt" "fmt"
"godo/libs" "godo/libs"
@ -34,12 +34,13 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"sync" "sync"
"time" "time"
) )
const ( const (
fileSize = 512 // 每个数据包的大小 GlobalfileSize = 512 // 每个数据包的大小
) )
type FileChunk struct { type FileChunk struct {
@ -146,7 +147,7 @@ func handleFile(filePath string, toIp string, message UdpMessage) {
fileSize := fileInfo.Size() fileSize := fileInfo.Size()
// 计算需要发送的数据包数量 // 计算需要发送的数据包数量
numChunks := (fileSize + fileSize - 1) / fileSize numChunks := (fileSize + GlobalfileSize - 1) / GlobalfileSize
// 发送文件 // 发送文件
SendFile(file, int(numChunks), toIp, fileSize, message) 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) wg.Add(1)
go func(index int) { go func(index int) {
defer wg.Done() defer wg.Done()
idStr := message.Type + "@" + message.Hostname + "@" + filepath.Base(file.Name()) + "@" + fmt.Sprintf("%d", fSize) + "@"
var chunkData [fileSize]byte fileLen := GlobalfileSize - len(idStr)
chunkData := make([]byte, fileLen)
n, err := file.Read(chunkData[:]) n, err := file.Read(chunkData[:])
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
log.Fatalf("Failed to read file chunk: %v", err) log.Fatalf("Failed to read file chunk: %v", err)
} }
// 创建文件块 //sendData(message, toIp)
chunk := FileChunk{ sendBinaryData(idStr, chunkData[:n], toIp)
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)
fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp) fmt.Printf("发送文件块 %d 到 %s 成功\n", index, toIp)
}(i) }(i)
} }
wg.Wait() wg.Wait()
} }
func sendBinaryData(idStr string, data []byte, toIp string) {
func sendData(message UdpMessage, toIp string) {
port := "56780" port := "56780"
addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%s", toIp, port)) addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%s", toIp, port))
if err != nil { if err != nil {
@ -213,30 +203,22 @@ func sendData(message UdpMessage, toIp string) {
} }
defer conn.Close() 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 { if err != nil {
log.Printf("Failed to write data: %v", err) log.Printf("Failed to write data: %v", err)
} }
} }
func ReceiveFile(msg UdpMessage) (string, error) { func ReceiveFiles(parts []string) (string, error) {
messageMap, ok := msg.Message.(map[string]interface{}) //fileType := parts[0]
if !ok { fileName := parts[2]
return "", fmt.Errorf("invalid message type: expected map[string]interface{}, got %T", msg.Message) fileSize, _ := strconv.ParseInt(parts[3], 10, 64)
} fileContent := []byte(parts[4])
// 从 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")
// }
// 创建接收文件的目录 // 创建接收文件的目录
baseDir, err := libs.GetOsDir() baseDir, err := libs.GetOsDir()
if err != nil { if err != nil {
@ -253,9 +235,8 @@ func ReceiveFile(msg UdpMessage) (string, error) {
return "", fmt.Errorf("failed to create receive directory") 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) { if _, err := os.Stat(filePath); os.IsNotExist(err) {
@ -266,23 +247,20 @@ func ReceiveFile(msg UdpMessage) (string, error) {
} }
defer file.Close() defer file.Close()
} }
// 打开或追加到现有文件
file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) file, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil { if err != nil {
log.Printf("Failed to open file: %v", err) log.Printf("Failed to open file: %v", err)
return "", fmt.Errorf("failed to open file") return "", fmt.Errorf("failed to open file")
} }
defer file.Close() defer file.Close()
// 写入数据 // 写入数据
n, err := file.Write(chunk.Data) n, err := file.Write(fileContent)
if err != nil { if err != nil {
log.Printf("Failed to write data to file: %v", err) log.Printf("Failed to write data to file: %v", err)
return "", fmt.Errorf("failed to write data to file") return "", fmt.Errorf("failed to write data to file")
} }
if n != len(chunk.Data) { if n != len(fileContent) {
log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(chunk.Data)) log.Printf("Incomplete write: wrote %d bytes, expected %d bytes", n, len(fileContent))
return "", fmt.Errorf("incomplete write") return "", fmt.Errorf("incomplete write")
} }
@ -291,7 +269,7 @@ func ReceiveFile(msg UdpMessage) (string, error) {
log.Printf("Failed to stat file: %v", err) log.Printf("Failed to stat file: %v", err)
return "", fmt.Errorf("failed to stat file") return "", fmt.Errorf("failed to stat file")
} }
if fileInfo.Size() == chunk.Filesize { if fileInfo.Size() == fileSize {
fmt.Println("文件接收完成且大小一致") fmt.Println("文件接收完成且大小一致")
return filePath, nil return filePath, nil
} else { } else {
@ -299,31 +277,3 @@ func ReceiveFile(msg UdpMessage) (string, error) {
return "", fmt.Errorf("file size mismatch") 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
}

57
godo/localchat/server.go

@ -28,6 +28,7 @@ import (
"godo/libs" "godo/libs"
"log" "log"
"net" "net"
"strings"
"time" "time"
) )
@ -92,16 +93,34 @@ func UdpServer() {
} }
log.Printf("Received UDP packet from %v: %s", remoteAddr, buffer[:n]) 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 地址 // 从 remoteAddr 获取 IP 地址
if udpAddr, ok := remoteAddr.(*net.UDPAddr); ok { if udpAddr, ok := remoteAddr.(*net.UDPAddr); ok {
ip := udpAddr.IP.String() 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 udpMsg.IP = ip
if udpMsg.Type == "heartbeat" { if udpMsg.Type == "heartbeat" {
@ -109,22 +128,22 @@ func UdpServer() {
continue continue
} }
if udpMsg.Type == "file" { // if udpMsg.Type == "file" {
ReceiveFile(udpMsg) // ReceiveFile(udpMsg)
continue // continue
} // }
if udpMsg.Type == "fileAccessed" { if udpMsg.Type == "fileAccessed" {
HandlerSendFile(udpMsg) HandlerSendFile(udpMsg)
continue continue
} }
if udpMsg.Type == "image" { // if udpMsg.Type == "image" {
filePath, err := ReceiveFile(udpMsg) // filePath, err := ReceiveFile(udpMsg)
if err != nil { // if err != nil {
log.Printf("error receiving image: %v", err) // log.Printf("error receiving image: %v", err)
continue // continue
} // }
udpMsg.Message = filePath // udpMsg.Message = filePath
} // }
// 添加消息到 UserMessages // 添加消息到 UserMessages
AddMessage(udpMsg) AddMessage(udpMsg)
} else { } else {

Loading…
Cancel
Save