127 lines
2.7 KiB
Go

// /futriis/internal/server/server.go
// Пакет server реализует серверную часть для клиент-серверной архитектуры
package server
import (
"bufio"
"encoding/json"
"net"
"sync"
"futriis/internal/engine"
"futriis/pkg/utils"
)
// Server представляет сервер СУБД
type Server struct {
address string
engine *engine.Engine
listener net.Listener
clients map[net.Conn]bool
mu sync.RWMutex
stopChan chan struct{}
}
// NewServer создаёт новый сервер
func NewServer(address string, engine *engine.Engine) *Server {
return &Server{
address: address,
engine: engine,
clients: make(map[net.Conn]bool),
stopChan: make(chan struct{}),
}
}
// Start запускает сервер
func (s *Server) Start() error {
listener, err := net.Listen("tcp", s.address)
if err != nil {
return err
}
s.listener = listener
utils.PrintSuccess("Сервер запущен на %s", s.address)
go s.acceptLoop()
return nil
}
// acceptLoop принимает входящие соединения
func (s *Server) acceptLoop() {
for {
select {
case <-s.stopChan:
return
default:
conn, err := s.listener.Accept()
if err != nil {
continue
}
s.mu.Lock()
s.clients[conn] = true
s.mu.Unlock()
go s.handleClient(conn)
}
}
}
// handleClient обрабатывает клиентское соединение
func (s *Server) handleClient(conn net.Conn) {
defer func() {
s.mu.Lock()
delete(s.clients, conn)
s.mu.Unlock()
conn.Close()
}()
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
line := scanner.Text()
// Парсим JSON запрос
var req map[string]interface{}
if err := json.Unmarshal([]byte(line), &req); err != nil {
// Если не JSON, обрабатываем как простую команду
result, err := s.engine.Execute(line)
s.sendResponse(conn, result, err)
} else {
// Обрабатываем JSON запрос
cmd, _ := req["command"].(string)
result, err := s.engine.Execute(cmd)
s.sendResponse(conn, result, err)
}
}
}
// sendResponse отправляет ответ клиенту
func (s *Server) sendResponse(conn net.Conn, result string, err error) {
response := make(map[string]interface{})
if err != nil {
response["error"] = err.Error()
} else {
response["result"] = result
}
data, _ := json.Marshal(response)
conn.Write(append(data, '\n'))
}
// Stop останавливает сервер
func (s *Server) Stop() {
close(s.stopChan)
if s.listener != nil {
s.listener.Close()
}
s.mu.Lock()
for conn := range s.clients {
conn.Close()
}
s.mu.Unlock()
}