最近又在看tcp服务的一些知识, 长连接编程还是有点意思, 今天试着写了个小玩意, 在服务端监听8808端口, 客户端连接上来后, 发送什么数据, 就返回什么数据.
如果用户发送的单个p字符, 服务端会给所有连接上来的用户广播消息快跑, 警察来了!!!, 有点意思.

代码如下:

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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

package main

import (
"net"
"log"
"sync"
"os"
"syscall"
"os/signal"
"fmt"
)

type Server struct{
closeChan chan bool
waitGroup *sync.WaitGroup
}

func NewServer() *Server {
return &Server{
make(chan bool),
&sync.WaitGroup{},
}
}

// ConnMgr connection manager object
type ConnMgr struct {
ConnList map[string]*net.TCPConn
}

var (
connmgr *ConnMgr
connMgrOnce *sync.Once = &sync.Once{}
)
func NewConnMgr() *ConnMgr {
if nil == connmgr {
connMgrOnce.Do(func() {
i := make(map[string]*net.TCPConn)
log.Println(i)
connmgr = &ConnMgr{i}
})
}
return connmgr
}

// getConnList get all connection from connection manager
func (connMgr *ConnMgr) getConnList() map[string]*net.TCPConn {
return connMgr.ConnList
}

// Add connection to connection manager
func (connMgr *ConnMgr) Add(conn *net.TCPConn) {
key := conn.RemoteAddr().String()
connMgr.ConnList[key] = conn
}

// HandleConn process coming connection
func (srv *Server) HandleConn(conn *net.TCPConn) {
defer conn.Close()
remoteAddr := conn.RemoteAddr().String()
connmgr := NewConnMgr()
connmgr.Add(conn)

fmt.Printf("remoteAddress 【%s】 Connected !\n", remoteAddr)
for {
select {
case <-srv.closeChan:
return
default:
}
buf := make([]byte, 2014)
l, err := conn.Read(buf)
if nil != err {
fmt.Printf("Read From Socket 【%v】 ! \n", err.Error())
return
}
fmt.Printf("Read raw Data: length 【%d】data【%s】 !", l, buf[:l])
reciveData := string(buf[:l])
if reciveData == "p" { // if user send char 'p' then broadcast to all connected user
go srv.Broadcast()
}
fmt.Printf("Read Data: 【%s】 !", reciveData)

sentData := []byte("哈哈, 世界")
data := fmt.Sprintf("【%s】===>【%s】\n", string(sentData), reciveData)
fmt.Println(data)
conn.Write([]byte(data))
}
}

// Broadcast all of connected connection
func (srv *Server) Broadcast() {
connmgr := NewConnMgr()
connList := connmgr.getConnList()

for ip, conn := range connList{
log.Println("broadcast to " + ip)
conn.Write([]byte("快跑, 警察来了!!!"))
}
}

func (srv *Server) Service(listener *net.TCPListener) {
for {
select {
case <-srv.closeChan:
return
default:
}

conn, err := listener.AcceptTCP()
if nil != err {
fmt.Println(err)
continue
}

srv.waitGroup.Add(1)
go (func() {
srv.HandleConn(conn)
srv.waitGroup.Done()
})()

}


}

func (srv *Server) Stop() {
close(srv.closeChan)
srv.waitGroup.Wait()
}


func main() {

network := "127.0.0.1:8808"
addr, err := net.ResolveTCPAddr("tcp", network)
if nil != err {
log.Fatal(err)
}
listener, err := net.ListenTCP("tcp", addr)
if nil != err {
log.Fatal(err)
}
srv := NewServer()
go srv.Service(listener)
log.Println("Listen:"+network)

stopChan := make(chan os.Signal)
signal.Notify(stopChan, syscall.SIGINT, syscall.SIGTERM)
<-stopChan

srv.Stop()
}