golang练习之聊天室——服务端增加消息转发功能

上一篇我们完成了客户端和服务端不停地发送接收消息的功能,接下来,我们要给服务端增加一个功能:在客户端端之间做消息转发。

要实现消息转发,首先要有客户列表。这个列表表示当前在线的客户,这样更容易实现。这可以在客户端连上来的时候就保存客户的信息。

客户之间发送消息的时候,用#隔开,前面是要发送到的客户端的ip和端口,后面是消息的内容。代码如下:

package main

import (
	"errors"
	"github.com/apex/log"
	"net"
	//"github.com/deckarep/golang-set"
	"strings"
)

func ParseClientMsg(msgPacket string) (string, string, error){
	listOfStr := strings.Split(msgPacket, "#")
	if len(listOfStr) < 2 {
		return "","",errors.New("message format error")
	}
	addr := listOfStr[0]
	msg := listOfStr[1]
	return addr,msg,nil
}

func HandleMsg() {
	for {
		msgPackage := <- msgQueue
		addr, msg, err := ParseClientMsg(msgPackage)
		clientConn, ok := clients[addr]
		if !ok {
			log.Error("client is offline")//最好是写回给客户端
			continue
		}
		_, err = clientConn.Write([]byte(msg))
		if err != nil {
			log.Error(err.Error())
			continue
		}
	}
}

func handleOneClient(client net.Conn) {
	defer client.Close()
	buf := make([]byte, 1024)
	for {
		nbytes, err := client.Read(buf)

		if err != nil {
			return
		}
		msgQueue <- string(buf[:nbytes])
	}
	log.Info("client close.")
}

var clients map[string]net.Conn
var msgQueue chan string

func PrintAllClient() string {
	var clientsList string
	for i := range clients {
		clientsList += i+"\n"
	}
	return clientsList
}

func main() {
	listener,err := net.Listen("tcp4", "127.0.0.1:54321")
	if err != nil {
		return
	}
	clients = make(map[string]net.Conn, 100)
	msgQueue = make(chan string, 200)
	go HandleMsg()
	for {
		oneClient, err := listener.Accept()
		if err != nil {
			continue
		}
		oneClient.Write([]byte(PrintAllClient()))
		clients[oneClient.RemoteAddr().String()] = oneClient
		go handleOneClient(oneClient)
	}
}

(全文完)

你可能感兴趣的:(go,golang)