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",
|
||||
"request": "launch",
|
||||
"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 {
|
||||
commandDefinition CommandDefinition
|
|
@ -1,4 +1,4 @@
|
|||
package commandlib
|
||||
package command
|
||||
|
||||
import "fmt"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package commandlib
|
||||
package command
|
||||
|
||||
import "strconv"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package commandlib
|
||||
package command
|
||||
|
||||
import "log"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package commandlib
|
||||
package command
|
||||
|
||||
import (
|
||||
"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