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() }