-
Notifications
You must be signed in to change notification settings - Fork 21
/
chat.go
121 lines (102 loc) · 2.13 KB
/
chat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
* Thank you to Drew Olson for his simple chat server that replays your chats to all connections (including yourself):
* https://gist.github.com/drewolson/3950226
*
* Pros:
* Simple
* Any number of telnet clients can connect
* Cons:
* Your own chats are mimic'ed back to your console
*
* How to use from any client:
* telnet <ip-address> 7777
*/
package main
import (
"bufio"
"net"
)
type Client struct {
incoming chan string
outgoing chan string
reader *bufio.Reader
writer *bufio.Writer
}
func (client *Client) Read() {
for {
line, _ := client.reader.ReadString('\n')
client.incoming <- line
}
}
func (client *Client) Write() {
for data := range client.outgoing {
client.writer.WriteString(data)
client.writer.Flush()
}
}
func (client *Client) Listen() {
go client.Read()
go client.Write()
}
func NewClient(connection net.Conn) *Client {
writer := bufio.NewWriter(connection)
reader := bufio.NewReader(connection)
client := &Client{
incoming: make(chan string),
outgoing: make(chan string),
reader: reader,
writer: writer,
}
client.Listen()
return client
}
type ChatRoom struct {
clients []*Client
joins chan net.Conn
incoming chan string
outgoing chan string
}
func (chatRoom *ChatRoom) Broadcast(data string) {
for _, client := range chatRoom.clients {
client.outgoing <- data
}
}
func (chatRoom *ChatRoom) Join(connection net.Conn) {
client := NewClient(connection)
chatRoom.clients = append(chatRoom.clients, client)
go func() {
for {
chatRoom.incoming <- <-client.incoming
}
}()
}
func (chatRoom *ChatRoom) Listen() {
go func() {
for {
select {
case data := <-chatRoom.incoming:
chatRoom.Broadcast(data)
case conn := <-chatRoom.joins:
chatRoom.Join(conn)
}
}
}()
}
func NewChatRoom() *ChatRoom {
chatRoom := &ChatRoom{
clients: make([]*Client, 0),
joins: make(chan net.Conn),
incoming: make(chan string),
outgoing: make(chan string),
}
chatRoom.Listen()
return chatRoom
}
func main() {
chatRoom := NewChatRoom()
listener, _ := net.Listen("tcp", ":7777")
for {
conn, _ := listener.Accept()
chatRoom.joins <- conn
}
}