点击(此处)折叠或打开
-
package main
-
-
import (
-
"bufio"
-
"bytes"
-
"fmt"
-
"net"
-
"sync"
-
"time"
-
)
-
-
var connMap map[string]*Heart = make(map[string]*Heart)
-
-
var rwLock *sync.RWMutex = new(sync.RWMutex)
-
-
var msgChan chan *Message = make(chan *Message, 100)
-
-
var addConnChan chan *Heart = make(chan *Heart,1)
-
-
var exitConnChan chan *Heart = make(chan *Heart,1)
-
-
func main() {
-
-
//新增连接
-
go func() {
-
for c := range addConnChan {
-
connMap[c.conn.RemoteAddr().String()] = c
-
}
-
}()
-
//退出连接
-
go func() {
-
for c := range exitConnChan {
-
delete(connMap, c.conn.RemoteAddr().String())
-
}
-
}()
-
//消息推送
-
go func() {
-
//遍历消息管道
-
for m := range msgChan {
-
for oneConn := range connMap {
-
if connMap[oneConn].conn.RemoteAddr().String() != m.conn.RemoteAddr().String() {
-
_, err := connMap[oneConn].conn.Write([]byte(m.message))
-
if err == nil {
-
//更新最后访问时间
-
connMap[oneConn].upTime()
-
}
-
}
-
}
-
}
-
-
}()
-
//心跳检测
-
go func() {
-
//定时器
-
timer := time.NewTimer(time.Duration(30) * time.Second)
-
for {
-
select {
-
case <-timer.C:
-
fmt.Println("timer up!")
-
currTime := time.Now()
-
fmt.Println("当前时间", currTime.Format("2006-01-02 15:04:05"))
-
for oneConn := range connMap {
-
//往客户端循环发送 心跳 如果30秒内发生过通讯的就不需要了
-
cha := currTime.Unix() - connMap[oneConn].lastUpTime
-
if cha > 30 {
-
connTime := time.Unix(connMap[oneConn].lastUpTime, 0)
-
fmt.Println("连接:", connMap[oneConn].conn.RemoteAddr().String(), ",最后更新时间:", connTime.Format("2006-01-02 15:04:05"))
-
_, err := connMap[oneConn].conn.Write([]byte("ping"))
-
if err != nil {
-
fmt.Println("连接断开", connMap[oneConn].conn.RemoteAddr().String())
-
delete(connMap, oneConn)
-
} else {
-
connMap[oneConn].upTime()
-
}
-
}
-
}
-
//重新调度
-
timer.Reset(time.Duration(30) * time.Second)
-
}
-
}
-
}()
-
-
l, err := net.Listen("tcp", "0.0.0.0:8088")
-
if err != nil {
-
panic(err)
-
}
-
for {
-
conn, err := l.Accept()
-
if err != nil {
-
fmt.Println("连接错误", err)
-
} else {
-
go func(conn net.Conn) {
-
-
defer func(conn net.Conn){
-
exitConnChan <- &Heart{
-
conn: conn,
-
lastUpTime: time.Now().Unix(),
-
}
-
conn.Close()
-
fmt.Println("关闭")
-
}(conn)
-
-
-
fmt.Println("新连接:", conn.RemoteAddr())
-
buffer := new(bytes.Buffer)
-
s := "welcome " + conn.RemoteAddr().String() + "!"
-
-
buffer.WriteString(s)
-
conn.Write(buffer.Bytes())
-
-
msgChan <- &Message{conn:conn,message:s}
-
-
//重置缓冲区
-
buffer.Reset()
-
-
addConnChan <- &Heart{
-
conn: conn,
-
lastUpTime: time.Now().Unix(),
-
}
-
-
fmt.Printf("connList %v ", connMap)
-
-
fmt.Println("在线人数", len(connMap))
-
-
//分隔符解析
-
input := bufio.NewScanner(conn)
-
for input.Scan() {
-
fmt.Println(input.Text())
-
-
buffer.WriteString(conn.RemoteAddr().String())
-
buffer.WriteString(":")
-
buffer.Write(input.Bytes())
-
buffer.WriteString("\r\n")
-
-
msgChan <- &Message{conn:conn,message:buffer.String()}
-
-
//重置缓冲区
-
buffer.Reset()
-
}
-
}(conn)
-
}
-
}
-
- }
点击(此处)折叠或打开
-
package main
-
-
import (
-
"net"
-
)
-
-
type Message struct {
-
conn net.Conn // tcp 连接
-
message string //消息内容
- }
点击(此处)折叠或打开
-
package main
-
-
import (
-
"net"
-
"time"
-
)
-
-
type Heart struct {
-
conn net.Conn // tcp 连接
-
lastUpTime int64 //最后更新时间
-
}
-
-
func (h *Heart) upTime() {
-
h.lastUpTime = time.Now().Unix()
- }