goland 简单聊天室服务端

Posted lemonzwt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了goland 简单聊天室服务端相关的知识,希望对你有一定的参考价值。

package main

import (
	"fmt"
	"net"
	"strings"
	"time"
)

type Client struct {
	C       chan string //用于发送数据的管道
	Name    string      //用户名
	Address string      //IP地址
}

//保存在线用户
var onLineMap map[string]Client

var message = make(chan string)

func Manager() {
	onLineMap = make(map[string]Client)
	for {
		msg := <-message //阻塞等待消息
		for _, cli := range onLineMap {
			cli.C <- msg
		}
	}
}

//发送消息给客户端
func WriteMessageToClient(cli Client, conn net.Conn) {
	for msg := range cli.C {
		//发送消息
		conn.Write([]byte(msg + "
"))
	}
}
func MakeMsg(cli Client, msg string) (buf string) {
	buf = "[" + cli.Address + "]" + cli.Name + ":" + msg
	return
}

//处理用户连接
func HandleConn(conn net.Conn) {
	defer conn.Close()
	//获取连接客户端网络地址
	cliAddr := conn.RemoteAddr().String()
	//创建用户结构体
	cli := Client{make(chan string), cliAddr, cliAddr}
	onLineMap[cliAddr] = cli

	//新建协程,发送消息给客户端
	go WriteMessageToClient(cli, conn)
	//广播某人在线
	message <- MakeMsg(cli, "login")
	cli.C <- MakeMsg(cli, "i am here")

	isQuit := make(chan bool)  //用户是否主动退出
	hasData := make(chan bool) //用户是否发送过数据
	//新建协程接收用户发送信息
	go func() {
		buf := make([]byte, 2048)
		for {
			n, err := conn.Read(buf)
			if n == 0 { //用户退出
				isQuit <- true
				fmt.Println("conn.Read err=", err)
				return
			}
			msg := string(buf[:n-1])
			if len(msg) == 3 && msg == "who" {
				//发送用户列表
				conn.Write([]byte("user list:
"))
				for _, data := range onLineMap {
					msg = data.Address + ":" + data.Name + "
"
					conn.Write([]byte(msg))
				}
			} else if len(msg) >= 8 && msg[:6] == "rename" {
				//修改用户名
				cli.Name = strings.Split(msg, "|")[1]
				onLineMap[cli.Address] = cli
				conn.Write([]byte("rename success
"))
			} else {
				//转发消息
				message <- MakeMsg(cli, msg)
			}
			hasData <- true
		}
	}()

	for {
		select {
		case <-isQuit:
			delete(onLineMap, cli.Address) //用户退出登录,移除用户
			message <- MakeMsg(cli, "login out")
			return
		case <-hasData:
		case <-time.After(60 * time.Second): //用户60秒不操作自动超时
			delete(onLineMap, cli.Address) //用户退出登录,移除用户
			message <- MakeMsg(cli, "time out leave out")
			return
		}
	}
}
func main() {
	//监听
	listener, err := net.Listen("tcp", ":8000")
	if err != nil {
		fmt.Println("net.Listen err=", err)
		return
	}
	defer listener.Close()

	//新建一个协程,转发消息
	go Manager()

	//主协程
	for {
		conn, err := listener.Accept()
		if err != nil {
			fmt.Println("listener.Accept err=", err)
			continue
		}
		go HandleConn(conn) //处理用户连接
	}
}

  

以上是关于goland 简单聊天室服务端的主要内容,如果未能解决你的问题,请参考以下文章

go语言实现简单的聊天室

一个hello/hi的简单的网络聊天程序

基于Netty的简单多人聊天程序(服务端)

Python聊天室

Laravel + Swoole 打造IM简易聊天室

Laravel + Swoole 打造IM简易聊天室