go实现聊天室【简洁版】

go写了一个简洁版的聊天室实现功能
1.广播用户登录
2.广播群发消息
3.修改当前登录用户名
4.广播用户退出

服务端代码

package main

import (
	"log"
	"net"
	"strings"
)
type Client struct {
	C chan string
	Name string
	Addr string
}
var onLineMap map[string]Client
var  Message=make(chan string)
var isQuit=make(chan bool)

func WriteMsg(clnt Client, conn net.Conn){
	for msg:=range clnt.C {
		msg:=msg+"\n"
		conn.Write([]byte(msg))
	}
}

//广播所有用户消息
func tellAllUser(conn net.Conn,clnt Client){
	addr:= conn.RemoteAddr().String()
	buf:=make([]byte,1024)
	for {
		n,err:=conn.Read(buf)
		if n == 0 {
			log.Println("客户端退休")
			isQuit <-true
			return
		}
		if err != nil {
			log.Println("system is errors")
			return
		}
		content:=string(buf[:n])
		if content == "who" && len(content) == 3 {
			conn.Write([]byte("用户列表:\n"))
			for _,item:=range onLineMap {
				userInfo:= item.Addr+":"+item.Name+"\n"
				conn.Write([]byte(userInfo))
			}
		}else if len(content) >=8 && content[:6] == "rename"{
			newName:= strings.Split(content,"|")
			clnt.Name = newName[1]
			onLineMap[addr]=clnt
		}else{
			msg:="客户端消息: "+content
			Message <-msg
		}

	}
}


//处理连接出来的用户
func HandleConnect(conn net.Conn){
	netAddr:=conn.RemoteAddr().String()
	clnt:=Client{
		C:make(chan string),
		Name: netAddr,
		Addr: netAddr,
	}
	//创建专门当前用户发送消息的go协程
	onLineMap[netAddr]=clnt
	go WriteMsg(clnt,conn)
	//发送用户上校消息导全局通道
	msg:="欢迎用户:"+netAddr+"登录"
	Message<-msg

	go tellAllUser(conn,clnt)//广播所有用户消息

	for {
		select {
			case <-isQuit:
			delete(onLineMap,netAddr)
			Message <-clnt.Name+"login out"
			return
		}
	}
}
func Manager(){
	onLineMap=make(map[string]Client)
	for {
		msg:=<-Message
		for _,clnt:=range onLineMap {
			clnt.C <-msg
		}
	}
}

func main(){
	listener,err:= net.Listen("tcp","127.0.0.1:8007")
	if err != nil {
		log.Println("open tcp is errors")
	}
	defer listener.Close()
	go Manager()//存储用户消息
	for {
		conn,err:=listener.Accept()
		if err != nil {
			log.Println("Accept is erros")
		}
		go HandleConnect(conn)
	}

}

客户端代码

package main

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"os"
	"strings"
)
func read(conn net.Conn){
	defer conn.Close()
	var buf[1024]byte
	reader:=bufio.NewReader(conn)
	for {
		n,err:=reader.Read(buf[:])
		if err  == io.EOF {
			break
		}
		if err != nil {
			return
		}
		recvStr:= string(buf[:n])
		fmt.Printf("收到服务端数据为:%v\n",recvStr)
	}
}

func main(){
	conn,err:= net.Dial("tcp","127.0.0.1:8007")
	if err != nil {
		fmt.Println("is erro")
	}
	go read(conn)
	reader:= bufio.NewReader(os.Stdin)
	fmt.Printf("%v,\n","请写入内容")
	for {
		text,_:=reader.ReadString('\n')
		text = strings.TrimSpace(text)
		if text == "exit" {
			break
		}
		conn.Write([]byte(text))
	}
	conn.Close()
}

posted on 2022-12-14 09:01  孤灯引路人  阅读(124)  评论(0编辑  收藏  举报

导航