golang,tcp服务——客户端

功能支持
|1.修改用户名————do r e n a m e rename rename"修改的用户名"
| 例如:修改用户名为java,do r e n a m e rename renamejava
|
|2.查看所有在线用户————do$list
|3.查看历史消息,最多支持查看10条
|4.用户上线提醒

全局变量,用于储存聊天历史记录

var MSGS []string

main.go文件

func main() {
	port := "39003"
	Listen, err := net.Listen("tcp", ":"+port)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println("Chatroom begin,listen port:", port)
	connMap := make(map[net.Conn]string)
	for {
		conn, err := Listen.Accept()
		defer conn.Close()
		if err != nil {
			fmt.Println(err.Error())
			continue
		}
		connMap[conn] = conn.RemoteAddr().String()
		//提醒用户上线
		notice(conn)
		//处理用户操作
		go HandlerConn(conn, connMap)
	}
}

处理每一个连接conn操作

func HandlerConn(conn net.Conn, connMap map[net.Conn]string) {
	buf := make([]byte, 1024)
	for {

		n, err := conn.Read(buf)
		if err != nil {
			// fmt.Println("conn数据读取失败" + err.Error())
			return
		}
		msg := strings.Trim(string(buf[:n]), "\r\n")
		fmt.Printf("msg: %v\n", msg)
		if strings.Contains(msg, "firstname") {
			name := strings.ReplaceAll(msg, "firstname", "")
			fisrtrename(conn, connMap, name)
			broadcastUserOnline(conn, connMap, name+"用户上线")
			fmt.Println(name + "用户上线")
			continue
		}

		handlerMsg(conn, connMap, msg)
	}
}

处理连接操作后,处理消息

消息操作,分为broadcast广播消息以及系统操作

当前支持操作,修改用户名,查看在线用户,查看历史聊天记录

func handlerMsg(conn net.Conn, connMap map[net.Conn]string, msg string) {
	parseArr := strings.Split(msg, "$")

	//判断消息是否为操作
	if len(parseArr) > 1 && parseArr[0] == "do" {
		//是——执行操作
		switch parseArr[1] {
		case "rename":
			{
				if len(parseArr) == 3 {
					name := parseArr[2]
					rename(conn, connMap, name)
				} else {
					returnerr(conn)
				}
			}
		case "list":
			{
				if len(parseArr) == 2 {
					list(conn, connMap)
				}
			}
		case "hy":
			{
				if len(parseArr) == 2 {
					getHistory(conn)
				}
			}
		default:
			{
				returnerr(conn)
			}
		}
	} else {
		//否——广播信息
		broadcast(conn, connMap, msg)
	}

}

操作函数——获取聊天记录

func getHistory(conn net.Conn) {
	allmsg := ""
	for num, msg := range MSGS {
		str := fmt.Sprintf("\n      *******第%d条*******", num+1)
		msg = str + msg
		allmsg += msg
	}
	conn.Write([]byte(allmsg))
}
func save10Msg(msg string) {
	MSGS = append(MSGS, msg)
	// MSGS = MSGS[10:]
}

操作函数——获取在线列表

func list(conn net.Conn, connMap map[net.Conn]string) {
	var listname string = ""

	for connCur, name := range connMap {
		_, err := connCur.Write([]byte("false"))
		if err != nil {
			delete(connMap, connCur)
			continue
		} else {
			fmt.Printf("name: %v\n", name)
		}
		listname = listname + name + "\n"
	}
	conn.Write([]byte(listname))

}

操作函数——修改用户名

func rename(conn net.Conn, connMap map[net.Conn]string, name string) {
	for connCur := range connMap {
		if connCur == conn {
			connMap[conn] = name
			recmsg := "操作成功,修改name为:" + name + "\n"
			conn.Write([]byte(recmsg))
		}
	}
}

广播消息操作

func broadcast(conn net.Conn, connMap map[net.Conn]string, msg string) {

	for connCur := range connMap {
		if conn == connCur {
			up := "\n==========历史信息============\n"
			msg := "time:" + time.Now().Format(" 15:04:05 ") + "\n" + "name:" + connMap[conn] + "\n" + "msg:" + msg + "\n"
			down := "===========历史信息===========\n\n"
			save10Msg(up + msg + down)
			continue
		}
		up := "\n==========历史信息============\n"
		msg := "time:" + time.Now().Format(" 15:04:05 ") + "\n" + "name:" + connMap[conn] + "\n" + "msg:" + msg + "\n"
		down := "===========历史信息===========\n\n"
		save10Msg(up + msg + down)
		str := []byte(msg)
		_, err := connCur.Write(str)
		if err != nil {
			// fmt.Println("broadcast fail", err.Error())
			delete(connMap, connCur)
			continue
		}
	}

}

其他函数①——提醒用户上线

func broadcastUserOnline(conn net.Conn, connMap map[net.Conn]string, msg string) {
	for connCur := range connMap {
		if conn == connCur {
			continue
		}
		fmt.Println("回写内容")
		str := []byte("time:" + time.Now().Format(" 15:04:05 ") + "\n" + "msg:" + msg + "\n")
		_, err := connCur.Write(str)
		if err != nil {
			// fmt.Println("broadcast fail", err.Error())
			delete(connMap, connCur)
			continue
		}
	}
}

其他函数②——处理用户名的初始化

func fisrtrename(conn net.Conn, connMap map[net.Conn]string, name string) {
	for connCur := range connMap {
		if connCur == conn {
			connMap[conn] = name
		}
	}
}

其他函数③——返回错误信息

func returnerr(conn net.Conn) {
	errmsg := "参数错误,请重新输入\n"
	conn.Write([]byte(errmsg))
}