package main
import (
"fmt"
"io"
"net"
"os"
"strings"
"time"
)
type Clinet struct {
Name string
Addr string
C chan string
}
var onlineMap map[string]Clinet
var message = make(chan string)
func ErrFucn(s string, e error) {
if e != nil {
fmt.Println(s, e)
os.Exit(1)
}
}
func MakeMsg(clt Clinet, msg string) (buf string) {
buf = fmt.Sprintf("[name:%s] => %s\n", clt.Name, msg)
return
}
func Manger() {
onlineMap = make(map[string]Clinet)
for {
msg := <-message
for _, cln := range onlineMap {
cln.C <- msg
}
}
}
func WriteToMsgClint(conn net.Conn, cln Clinet) {
for msg := range cln.C {
conn.Write([]byte(msg))
}
}
func HandlerConnent(conn net.Conn) {
defer conn.Close()
netAddr := conn.RemoteAddr().String()
isQuit := make(chan bool)
hasDate := make(chan bool)
// 全局广播
clnt := Clinet{netAddr, netAddr, make(chan string)}
onlineMap[clnt.Addr] = clnt
go WriteToMsgClint(conn, clnt)
message <- MakeMsg(clnt, "LOGIN")
// 聊天室
go func() {
buf := make([]byte, 4096)
for {
n, err := conn.Read(buf)
if n == 0 {
isQuit <- true
return
}
if err != nil && err != io.EOF {
fmt.Println("conn.Read err: ", err)
return
}
msg := string(buf[:n-1])
if msg == "who" && len(msg) == 3 {
conn.Write([]byte("USER LIST:\n"))
for _, u := range onlineMap {
userInfo := fmt.Sprintf("[IP:%s] [NAME:%s]\n", u.Addr, u.Name)
conn.Write([]byte(userInfo))
}
} else if len(msg) >= 8 && msg[:6] == "rename" {
newUser := strings.Split(msg, "|")[1]
clnt.Name = newUser
onlineMap[clnt.Addr] = clnt
conn.Write([]byte("用户更新成功!!!\n"))
} else {
message <- MakeMsg(clnt, msg)
}
hasDate <- true
}
}()
for {
select {
case <-isQuit:
close(clnt.C)
delete(onlineMap, clnt.Addr)
message <- MakeMsg(clnt, "LOGOUT")
return
case <-hasDate:
//
case <-time.After(time.Second * 10):
close(clnt.C)
delete(onlineMap, clnt.Addr)
message <- MakeMsg(clnt, "OVERTIME")
return
}
}
}
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:8080")
ErrFucn("net.Listen err", err)
defer listener.Close()
go Manger()
for {
conn, err := listener.Accept()
ErrFucn("listener.Accept err:", err)
go HandlerConnent(conn)
}
}
本文章使用limfx的vscode插件快速发布