TCP server works
This commit is contained in:
parent
82082b128f
commit
e6da93f48f
17 changed files with 226 additions and 108 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
@ -9,7 +9,7 @@
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "debug",
|
"mode": "debug",
|
||||||
"program": "${workspaceFolder}/src/Server/main.go"
|
"program": "${workspaceFolder}/cmd/lastmudserver/main.go"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
37
cmd/lastmudserver/main.go
Normal file
37
cmd/lastmudserver/main.go
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.haedhutner.dev/mvv/LastMUD/internal/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println(`\\\\---------------------////`)
|
||||||
|
fmt.Println(`|||| LastMUD Server ||||`)
|
||||||
|
fmt.Println(`////---------------------\\\\`)
|
||||||
|
|
||||||
|
lastMudServer, err := server.CreateServer(":8000")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go lastMudServer.Listen()
|
||||||
|
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
|
||||||
|
for {
|
||||||
|
text, _ := reader.ReadString('\n')
|
||||||
|
text = strings.ReplaceAll(text, "\n", "")
|
||||||
|
|
||||||
|
if strings.Compare("exit", text) == 0 {
|
||||||
|
lastMudServer.Stop()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
go.mod
Normal file
5
go.mod
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module code.haedhutner.dev/mvv/LastMUD
|
||||||
|
|
||||||
|
go 1.24.4
|
||||||
|
|
||||||
|
require github.com/google/uuid v1.6.0
|
2
go.sum
Normal file
2
go.sum
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
@ -1,4 +1,4 @@
|
||||||
package commandlib
|
package command
|
||||||
|
|
||||||
type Command struct {
|
type Command struct {
|
||||||
commandDefinition CommandDefinition
|
commandDefinition CommandDefinition
|
|
@ -1,4 +1,4 @@
|
||||||
package commandlib
|
package command
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package commandlib
|
package command
|
||||||
|
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package commandlib
|
package command
|
||||||
|
|
||||||
import "log"
|
import "log"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package commandlib
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
75
internal/server/connection.go
Normal file
75
internal/server/connection.go
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Connection struct {
|
||||||
|
identity uuid.UUID
|
||||||
|
|
||||||
|
conn net.Conn
|
||||||
|
|
||||||
|
inputChannel chan string
|
||||||
|
closeChannel chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateConnection(conn net.Conn) *Connection {
|
||||||
|
return &Connection{
|
||||||
|
identity: uuid.New(),
|
||||||
|
conn: conn,
|
||||||
|
inputChannel: make(chan string),
|
||||||
|
closeChannel: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) listen() (err error) {
|
||||||
|
defer c.conn.Close()
|
||||||
|
|
||||||
|
c.conn.SetReadDeadline(time.Time{})
|
||||||
|
|
||||||
|
for {
|
||||||
|
if c.shouldClose() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
message, err := bufio.NewReader(c.conn).ReadString('\n')
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.inputChannel <- message
|
||||||
|
|
||||||
|
c.conn.Write([]byte(message))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) shouldClose() bool {
|
||||||
|
select {
|
||||||
|
case <-c.closeChannel:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Close() {
|
||||||
|
c.closeChannel <- struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) NextInput() (next string, err error) {
|
||||||
|
select {
|
||||||
|
case val := <-c.inputChannel:
|
||||||
|
return val, nil
|
||||||
|
default:
|
||||||
|
return "", newInputEmptyError()
|
||||||
|
}
|
||||||
|
}
|
15
internal/server/error.go
Normal file
15
internal/server/error.go
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
type inputEmptyError struct {
|
||||||
|
msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInputEmptyError() *inputEmptyError {
|
||||||
|
return &inputEmptyError{
|
||||||
|
msg: "No input available at this moment",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *inputEmptyError) Error() string {
|
||||||
|
return err.msg
|
||||||
|
}
|
86
internal/server/server.go
Normal file
86
internal/server/server.go
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
listener *net.TCPListener
|
||||||
|
|
||||||
|
connections []*Connection
|
||||||
|
|
||||||
|
stopChannel chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateServer(port string) (srv *Server, err error) {
|
||||||
|
addr, err := net.ResolveTCPAddr("tcp", port)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ln, err := net.ListenTCP("tcp", addr)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Listening on port", port)
|
||||||
|
|
||||||
|
srv = &Server{
|
||||||
|
listener: ln,
|
||||||
|
connections: []*Connection{},
|
||||||
|
stopChannel: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) Listen() {
|
||||||
|
// Wait for 200 millis for a new connection, and loop if none found in that time
|
||||||
|
srv.listener.SetDeadline(time.Now().Add(1 * time.Second))
|
||||||
|
|
||||||
|
for {
|
||||||
|
if srv.shouldStop() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := srv.listener.Accept()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
c := CreateConnection(conn)
|
||||||
|
srv.connections = append(srv.connections, c)
|
||||||
|
|
||||||
|
go c.listen()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range srv.connections {
|
||||||
|
v.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
err := srv.listener.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) shouldStop() bool {
|
||||||
|
select {
|
||||||
|
case <-srv.stopChannel:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (srv *Server) Stop() {
|
||||||
|
srv.stopChannel <- struct{}{}
|
||||||
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
module code.haedhutner.dev/mvv/LastMUD/CommandLib
|
|
||||||
|
|
||||||
go 1.24.4
|
|
|
@ -1,6 +0,0 @@
|
||||||
module code.haedhutner.dev/mvv/LastMUD/CoreLib
|
|
||||||
|
|
||||||
require code.haedhutner.dev/mvv/LastMUD/CommandLib v0.0.0
|
|
||||||
replace code.haedhutner.dev/mvv/LastMUD/CommandLib => ../CommandLib
|
|
||||||
|
|
||||||
go 1.24.4
|
|
|
@ -1,13 +0,0 @@
|
||||||
module code.haedhutner.dev/mvv/LastMUD/Server
|
|
||||||
|
|
||||||
require (
|
|
||||||
code.haedhutner.dev/mvv/LastMUD/CommandLib v0.0.0
|
|
||||||
code.haedhutner.dev/mvv/LastMUD/CoreLib v0.0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
replace (
|
|
||||||
code.haedhutner.dev/mvv/LastMUD/CommandLib => ../CommandLib
|
|
||||||
code.haedhutner.dev/mvv/LastMUD/CoreLib => ../CoreLib
|
|
||||||
)
|
|
||||||
|
|
||||||
go 1.24.4
|
|
|
@ -1,80 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Command interface {
|
|
||||||
Name() string
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
ln, err := net.Listen("tcp", ":8000")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Listening on port 8000")
|
|
||||||
|
|
||||||
conn, err := ln.Accept()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// cmdRegistry := commandlib.CreateCommandRegistry(
|
|
||||||
// commandlib.CreateCommandDefinition(
|
|
||||||
// "exit",
|
|
||||||
// func(tokens []commandlib.Token) bool {
|
|
||||||
// return tokens[0].Lexeme() == "exit"
|
|
||||||
// },
|
|
||||||
// func(tokens []commandlib.Token) []commandlib.Parameter {
|
|
||||||
// return nil
|
|
||||||
// },
|
|
||||||
// func(parameters ...commandlib.Parameter) (err error) {
|
|
||||||
// err = conn.Close()
|
|
||||||
// return
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
|
|
||||||
for {
|
|
||||||
message, _ := bufio.NewReader(conn).ReadString('\n')
|
|
||||||
response := ""
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
|
|
||||||
// if err == io.EOF {
|
|
||||||
// fmt.Println("Client disconnected")
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
|
|
||||||
// log.Println("Read error:", err)
|
|
||||||
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
|
|
||||||
conn.Write([]byte(message + "\n"))
|
|
||||||
|
|
||||||
// cmdContext, err := commandlib.CreateCommandContext(cmdRegistry, message)
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
// log.Println(err)
|
|
||||||
// response = err.Error()
|
|
||||||
// } else {
|
|
||||||
// // err = cmdContext.ExecuteCommand()
|
|
||||||
|
|
||||||
// // if err != nil {
|
|
||||||
// // log.Println(err)
|
|
||||||
// // response = err.Error()
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
|
|
||||||
conn.Write([]byte(response + "\n> "))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue