更换位置
This commit is contained in:
72
server/db.go
Normal file
72
server/db.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
func InitDB() {
|
||||
var err error
|
||||
db, err = sql.Open("sqlite3", "./chat.db")
|
||||
if err != nil {
|
||||
log.Fatalf("打开数据库失败: %v", err)
|
||||
}
|
||||
|
||||
createTableSQL := `
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
sender TEXT NOT NULL,
|
||||
receiver TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
timestamp DATETIME NOT NULL
|
||||
);
|
||||
`
|
||||
_, err = db.Exec(createTableSQL)
|
||||
if err != nil {
|
||||
log.Fatalf("创建表失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func SaveMessage(sender, receiver, content string) error {
|
||||
stmt, err := db.Prepare("INSERT INTO messages(sender, receiver, content, timestamp) VALUES (?, ?, ?, ?)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stmt.Close()
|
||||
|
||||
_, err = stmt.Exec(sender, receiver, content, time.Now())
|
||||
return err
|
||||
}
|
||||
|
||||
func GetMessages(sender, receiver string) ([]Message, error) {
|
||||
rows, err := db.Query("SELECT sender, receiver, content, timestamp FROM messages WHERE (sender = ? AND receiver = ?) OR (sender = ? AND receiver = ?) ORDER BY timestamp ASC", sender, receiver, receiver, sender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var messages []Message
|
||||
for rows.Next() {
|
||||
var msg Message
|
||||
var ts string
|
||||
err = rows.Scan(&msg.Sender, &msg.Receiver, &msg.Content, &ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg.Timestamp, _ = time.Parse(time.RFC3339, ts)
|
||||
messages = append(messages, msg)
|
||||
}
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
Sender string
|
||||
Receiver string
|
||||
Content string
|
||||
Timestamp time.Time
|
||||
}
|
59
server/file_transfer.go
Normal file
59
server/file_transfer.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
// 服务器端接收文件的示例函数
|
||||
func ReceiveFile(conn net.Conn, filename string, filesize int64) error {
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var received int64 = 0
|
||||
buf := make([]byte, 4096)
|
||||
for received < filesize {
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return err
|
||||
}
|
||||
file.Write(buf[:n])
|
||||
received += int64(n)
|
||||
}
|
||||
fmt.Printf("文件 %s 接收完成,共 %d 字节\n", filename, received)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 服务器端发送文件的示例函数
|
||||
func SendFile(conn net.Conn, filepath string) error {
|
||||
file, err := os.Open(filepath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
n, err := file.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return err
|
||||
}
|
||||
_, err = conn.Write(buf[:n])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Printf("文件 %s 发送完成\n", filepath)
|
||||
return nil
|
||||
}
|
75
server/main.go
Normal file
75
server/main.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
clients = make(map[net.Conn]string) // 连接映射:连接对象到用户名
|
||||
clientsMu sync.Mutex // 保护clients的互斥锁
|
||||
)
|
||||
|
||||
func main() {
|
||||
listener, err := net.Listen("tcp", ":8888")
|
||||
if err != nil {
|
||||
log.Fatalf("监听端口失败: %v", err)
|
||||
}
|
||||
defer listener.Close()
|
||||
fmt.Println("服务器已启动,监听端口 8888")
|
||||
|
||||
for {
|
||||
conn, err := listener.Accept()
|
||||
if err != nil {
|
||||
log.Printf("接受连接失败: %v", err)
|
||||
continue
|
||||
}
|
||||
go handleConnection(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handleConnection(conn net.Conn) {
|
||||
defer func() {
|
||||
// 连接关闭时,移除客户端
|
||||
clientsMu.Lock()
|
||||
delete(clients, conn)
|
||||
clientsMu.Unlock()
|
||||
conn.Close()
|
||||
broadcast(fmt.Sprintf("用户退出:%s", conn.RemoteAddr().String()), "系统")
|
||||
fmt.Printf("客户端断开:%s\n", conn.RemoteAddr().String())
|
||||
}()
|
||||
|
||||
// 添加新连接
|
||||
clientsMu.Lock()
|
||||
clients[conn] = conn.RemoteAddr().String()
|
||||
clientsMu.Unlock()
|
||||
|
||||
// 通知所有客户端有新用户加入
|
||||
broadcast(fmt.Sprintf("新用户加入:%s", conn.RemoteAddr().String()), "系统")
|
||||
|
||||
scanner := bufio.NewScanner(conn)
|
||||
for scanner.Scan() {
|
||||
msg := scanner.Text()
|
||||
sender := clients[conn]
|
||||
broadcast(msg, sender)
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Printf("读取消息错误: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func broadcast(message, sender string) {
|
||||
clientsMu.Lock()
|
||||
defer clientsMu.Unlock()
|
||||
for c := range clients {
|
||||
if c != nil {
|
||||
_, err := fmt.Fprintf(c, "[%s] %s\n", sender, message)
|
||||
if err != nil {
|
||||
log.Printf("广播失败: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
server/server
Normal file
BIN
server/server
Normal file
Binary file not shown.
Reference in New Issue
Block a user