go实现简单聊天

2018/04/10
简单的go聊天实现 心跳检测

上代码


package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net"
	"time"
)

var ConnMap = make(map[string]net.Conn)

//主文件
func main() {
	li, err := net.Listen("tcp", ":8090")
	if err != nil {
		log.Panic(err)
	}
	for {
		conn, err := li.Accept()

		if err != nil {
			log.Panic(err)
		}
		go handleTCP(conn)
		go heartbeat(conn)
	}
}

//心跳检测

func heartbeat(conn net.Conn) {
	ticker := time.NewTicker(time.Second * 5)

	for t := range ticker.C {
		fmt.Printf("current client num :%d---->%d\n", len(ConnMap), t.Unix())

		for name, v := range ConnMap {
			_, err := v.Write([]byte("ping")) //心跳检测
			if err != nil {
				fmt.Printf("client %s is close!\n", conn.RemoteAddr().String())
				conn.Close()

				fmt.Printf("client %s is name!\n", name)
				delete(ConnMap, name)

				continue //跳出去执行下个
			}
		}

	}
}

//监听链接
func handleTCP(conn net.Conn) {
	defer conn.Close()
	for {
		data := make([]byte, 1024)
		con_len, err := conn.Read(data)

		if err == io.EOF { //判断客户端离开
			fmt.Printf("client %s is close!\n", conn.RemoteAddr().String())
			break
		}

		if err != nil {
			conn.Close()
			break
		}
		var m Message
		json.Unmarshal(data[:con_len], &m) //解析自动以数据

		fmt.Println(m)

		fmt.Println(m.Flags)

		switch m.Flags {
		case 1: //进行注册
			if _, ok := ConnMap[m.Name]; ok {
				conn.Write([]byte("Bindings"))
				//conn.Write([]byte("已绑定"))
			} else {
				ConnMap[m.Name] = conn
			}
		case 2: //全部广播
			for _, v := range ConnMap {
				v.Write([]byte(m.Content)) //发送数据
			}
		case 3: //单发
			ConnMap[m.Name].Write([]byte(m.Content))
		default:
			conn.Write([]byte("请先绑定"))
		}
	}
}

type Message struct {
	Id      int
	Name    string
	Flags   int //1 注册 2发送全部 3发送个人
	Content string
}



//然后下载sokit客户端
链接8090端口

Flags 1 注册用户 2发送广播 3 私聊

发送数据   注册用户:{"Id":2,"Name":"chengpenghui","Flags":1,"Content":"reg"}



带流协议自定的代码:
func handleTCP(conn net.Conn) {
	defer conn.Close()
	buf := make([]byte, 1024)
	var jsonBuf bytes.Buffer
	for {
		n, err := conn.Read(buf)
		if err == io.EOF { //判断客户端离开
			fmt.Printf("client %s is close!\n", conn.RemoteAddr().String())
			break
		}
		if err != nil {
			conn.Close()
			break
		}

		if buf[n-1] == 110 { //等于\n 一次就读取完毕
			fmt.Println(string(buf[:n-1]))
			jsonBuf.Write(buf[:n-1])
			jsonBuf.Reset() //清空buf
		} else { //没有\n一次没有读取完毕,继续读取
			jsonBuf.Write(buf[:n])
			continue
		}

		var m Message
		json.Unmarshal(jsonBuf.Bytes(), &m) //解析自动以数据

		fmt.Println(m)

		switch m.Flags {
		case 1: //进行注册
			if _, ok := ConnMap[m.Name]; ok {
				conn.Write([]byte("Bindings"))
				//conn.Write([]byte("已绑定"))
			} else {
				ConnMap[m.Name] = conn
			}
		case 2: //全部广播
			for _, v := range ConnMap {
				v.Write([]byte(m.Content)) //发送数据
			}
		case 3: //单发
			ConnMap[m.Name].Write([]byte(m.Content))
		default:
			conn.Write([]byte("请先绑定"))
		}
	}
}


func handleConn(conn net.Conn) {
    reader := bufio.NewReader(conn)
    var jsonBuf bytes.Buffer
    for {
        // 读取一行数据,交给后台处理
        line,isPrefix,err := reader.ReadLine()
        if len(line) > 0{
            jsonBuf.Write(line)
            if !isPrefix{
                executeBytes(jsonBuf.Bytes())
                jsonBuf.Reset()
            }
        }
        if err != nil{
            break
        }
    }
    conn.Close()
}


个人随笔

安静的等待,你若盛开,蝴蝶自来

承接高质量 网站开发 app开发 如有需要请点击About联系

@承鹏辉