并发聊天服务器
package main
import (
"fmt"
"net"
"strings"
"time"
)
type Client struct {
C chan string
Name string
Addr string
}
var onlineMap map [ string ] Client
var message = make ( chan string )
func MakeMsg ( cli Client, msg string ) ( buf string ) {
buf = "[" + cli. Addr + "]" + cli. Name + ": " + msg
return
}
func WriteMsgToClient ( cli Client, conn net. Conn) {
for msg := range cli. C {
_ , err := conn. Write ( [ ] byte ( msg + "\n" ) )
if err != nil {
fmt. Println ( "conn write err =" , err)
return
}
}
}
func HandleConn ( conn net. Conn) {
defer conn. Close ( )
cliAddr := conn. RemoteAddr ( ) . String ( )
cli := Client{ make ( chan string ) , cliAddr, cliAddr}
onlineMap[ cliAddr] = cli
go WriteMsgToClient ( cli, conn)
message <- MakeMsg ( cli, "login" )
cli. C <- MakeMsg ( cli, "I am hello" )
isQuit := make ( chan bool )
isData := make ( chan bool )
go func ( ) {
buf := make ( [ ] byte , 2048 )
for {
readSize, err := conn. Read ( buf)
if readSize == 0 {
isQuit <- true
fmt. Println ( "conn read err = " , err)
return
}
msg := string ( buf[ : readSize- 1 ] )
if len ( msg) == 3 && msg == "who" {
conn. Write ( [ ] byte ( "user list:\n" ) )
for _ , tmp := range onlineMap {
msg = tmp. Addr + ":" + tmp. Name + "\n"
conn. Write ( [ ] byte ( msg) )
}
} else if len ( msg) >= 8 && msg[ : 6 ] == "rename" {
name := strings. Split ( msg, "|" ) [ 1 ]
cli. Name = name
onlineMap[ cliAddr] = cli
conn. Write ( [ ] byte ( "rename ok\n" ) )
} else {
fmt. Println ( "成朋" )
message <- MakeMsg ( cli, msg)
}
isData <- true
}
} ( )
for true {
select {
case <- isQuit:
delete ( onlineMap, cliAddr)
message <- MakeMsg ( cli, "login out" )
return
case <- isData:
case <- time. After ( 30 * time. Second) :
delete ( onlineMap, cliAddr)
message <- MakeMsg ( cli, "time out leave out" )
return
}
}
}
func Manager ( ) {
onlineMap = make ( map [ string ] Client)
for true {
meg := <- message
for _ , client := range onlineMap {
client. C <- meg
}
}
}
func main ( ) {
listener, err := net. Listen ( "tcp" , ":8000" )
if err != nil {
fmt. Println ( "listener err = " , err)
return
}
defer listener. Close ( )
go Manager ( )
for true {
conn, err := listener. Accept ( )
if err != nil {
fmt. Println ( "conn err = " , err)
continue
}
go HandleConn ( conn)
}
}
调试工具netcat