上一篇我们完成了客户端和服务端不停地发送接收消息的功能,接下来,我们要给服务端增加一个功能:在客户端端之间做消息转发。
要实现消息转发,首先要有客户列表。这个列表表示当前在线的客户,这样更容易实现。这可以在客户端连上来的时候就保存客户的信息。
客户之间发送消息的时候,用#隔开,前面是要发送到的客户端的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)
}
}
(全文完)