chatserver
This commit is contained in:
parent
72c34f3568
commit
872b216455
1
.gitignore
vendored
1
.gitignore
vendored
@ -49,3 +49,4 @@ tcpserver/tcpserver
|
|||||||
echoserver/echoserver
|
echoserver/echoserver
|
||||||
example-redis/example-redis
|
example-redis/example-redis
|
||||||
echorot13/echorot13
|
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