-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.go
110 lines (99 loc) · 1.95 KB
/
server.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
package main
import (
"fmt"
"log"
"net"
"os"
)
type client chan<- string
var (
entering = make(chan client)
leaving = make(chan client)
messages = make(chan string)
users = make(map[string]bool)
)
func main() {
ip := os.Getenv("IP")
if ip == "" {
ip = "localhost"
}
port := os.Getenv("PORT")
if port == "" {
port = "9700"
}
listenAddress := ip + ":" + port
listener, err := net.Listen("tcp", listenAddress)
if err != nil {
log.Fatal(err)
}
log.Println("listening on", listenAddress)
go broadcaster()
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
continue
}
go handleConn(conn)
}
}
func broadcaster() {
clients := make(map[client]bool)
for {
select {
case msg := <-messages:
for cli := range clients {
cli <- msg
}
case cli := <-entering:
clients[cli] = true
case cli := <-leaving:
delete(clients, cli)
close(cli)
}
}
}
func handleConn(conn net.Conn) {
defer func() { _ = conn.Close() }()
ch := make(chan string)
go clientWriter(conn, ch)
// 欢迎消息
who := conn.RemoteAddr().String()
ch <- "本聊天室采用 AES 对称加密,无明文传输"
ch <- "You are " + who
if len(users) == 0 {
ch <- "no one is in this chatroom"
} else {
for addr := range users {
ch <- addr + " is in this chatroom too"
}
}
users[who] = true
// 入场通知
messages <- who + " has arrived"
entering <- ch
// 检测输入
tcpPacket := make(chan []byte)
go listenConn(conn, tcpPacket)
for bytes := range tcpPacket {
decryptedMsg, err := decrypt(bytes)
if err != nil {
log.Println(err)
}
messages <- who + ": " + string(decryptedMsg)
}
// 离场通知
leaving <- ch
messages <- who + " has left"
delete(users, who)
}
// 消息出口,所有出口消息都加密了
func clientWriter(conn net.Conn, ch <-chan string) {
for msg := range ch {
encryptedMsg, err := encrypt([]byte(msg))
if err != nil {
fmt.Println(err)
}
conn.Write(packet(encryptedMsg))
}
}