chatserver
This commit is contained in:
parent
72c34f3568
commit
872b216455
1
.gitignore
vendored
1
.gitignore
vendored
@ -49,3 +49,4 @@ tcpserver/tcpserver
|
||||
echoserver/echoserver
|
||||
example-redis/example-redis
|
||||
echorot13/echorot13
|
||||
chatserver/chatserver
|
||||
|
144
chatserver/main.go
Normal file
144
chatserver/main.go
Normal file
@ -0,0 +1,144 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Connection *net.Conn
|
||||
Name string
|
||||
Send chan string
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
cli *Client
|
||||
message string
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
net.Listener
|
||||
Clients []Client
|
||||
NewClients chan Client
|
||||
NewMessages chan Message
|
||||
}
|
||||
|
||||
func (cli Client) Prompt() string {
|
||||
return "<" + cli.Name + "> "
|
||||
}
|
||||
|
||||
func (cli Client) SendMessages() {
|
||||
for msg := range cli.Send {
|
||||
io.WriteString(*cli.Connection, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (cli Client) WaitMessage(server *Server) {
|
||||
scanner := bufio.NewScanner(*cli.Connection)
|
||||
io.WriteString(*cli.Connection, cli.Prompt())
|
||||
for scanner.Scan() {
|
||||
msg := Message{&cli, scanner.Text()}
|
||||
if len(msg.message) > 0 {
|
||||
log.Println("New message from", cli.Name, msg.message)
|
||||
server.NewMessages <- msg
|
||||
}
|
||||
io.WriteString(*cli.Connection, cli.Prompt())
|
||||
}
|
||||
}
|
||||
|
||||
func NewServer(addr string) (*Server, error) {
|
||||
ln, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Server{
|
||||
ln,
|
||||
make([]Client, 0),
|
||||
make(chan Client),
|
||||
make(chan Message),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (server *Server) NewClient(conn *net.Conn) {
|
||||
io.WriteString(*conn, "What is your name? ")
|
||||
scanner := bufio.NewScanner(*conn)
|
||||
for scanner.Scan() {
|
||||
str := scanner.Text()
|
||||
log.Println("New client", str)
|
||||
cli := &Client{
|
||||
conn,
|
||||
str,
|
||||
make(chan string),
|
||||
}
|
||||
server.NewClients <- *cli
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) MessageDispatcher() {
|
||||
for msg := range server.NewMessages {
|
||||
log.Println("Dispatching message", msg.message, "from", msg.cli.Name)
|
||||
for _, dest := range server.Clients {
|
||||
if dest.Name != msg.cli.Name {
|
||||
log.Println("Send message", msg.message, "from", msg.cli.Name, "to", dest.Name)
|
||||
dest.Send <- "\n" + msg.cli.Prompt() + msg.message + "\n" + dest.Prompt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) CreateClients() {
|
||||
for cli := range server.NewClients {
|
||||
exists := false
|
||||
for _, c := range server.Clients {
|
||||
if c.Name == cli.Name {
|
||||
exists = true
|
||||
}
|
||||
}
|
||||
if exists {
|
||||
io.WriteString(*cli.Connection, "Name already in use\n")
|
||||
go server.NewClient(cli.Connection)
|
||||
} else {
|
||||
server.Clients = append(server.Clients, cli)
|
||||
log.Println("Client ready to chat", cli.Name)
|
||||
log.Println(len(server.Clients), "clients connected")
|
||||
go cli.WaitMessage(server)
|
||||
go cli.SendMessages()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wait connections from clients
|
||||
func (server *Server) handle() {
|
||||
for {
|
||||
conn, err := server.Accept()
|
||||
if err != nil {
|
||||
log.Println("Connection error", err)
|
||||
}
|
||||
go server.NewClient(&conn)
|
||||
// TODO disconnect?
|
||||
}
|
||||
defer server.stop()
|
||||
}
|
||||
|
||||
func (server *Server) stop() {
|
||||
// TODO close connections
|
||||
defer server.Close()
|
||||
}
|
||||
|
||||
func (server *Server) start() {
|
||||
log.Println("Starting server...")
|
||||
go server.MessageDispatcher()
|
||||
go server.CreateClients() // create client one at a time (race condition)
|
||||
server.handle()
|
||||
}
|
||||
|
||||
func main() {
|
||||
server, err := NewServer(":9000")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
server.start()
|
||||
}
|
Loading…
Reference in New Issue
Block a user