127 lines
2.7 KiB
Go
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()
|
|
}
|