Server
package main
import (
"net"
"fmt"
"time"
"strings"
)
type Client struct {
C chan string
Name string
Addr string
}
var onlineClient=make(map[string]Client)
var message=make(chan string)
func main() {
listener,err:=net.Listen("tcp","127.0.0.1:8000")
if err!=nil {
fmt.Println(err)
return
}
defer listener.Close()
go Manager()
for {
conn,err:=listener.Accept()
if err!=nil {
fmt.Println(err)
continue
}
go func(conn net.Conn) {
defer conn.Close()
addr:=conn.RemoteAddr().String()
client:=Client{make(chan string),addr,addr}
onlineClient[addr]=client
go SendMessageToClient(client,conn)
message<-MakeMessage(client,"login")
isQuit:=make(chan bool)
go func() {
m:=make([]byte,4096)
for {
n,err:=conn.Read(m)
if n==0 {
isQuit<-true
return
}
if err!=nil {
fmt.Println(err)
return
}
x:=string(m[:n-1])
if x=="who" {
conn.Write([]byte("online user\n"))
for _,user:=range onlineClient{
conn.Write([]byte(user.Name+" "+user.Addr+"\n"))
}
} else if len(x)>=8 && x[:6]=="rename" {
newname:=strings.Split(x,"|")[1]
client.Name=newname
onlineClient[addr]=client
conn.Write([]byte("rename successful\n"))
} else {
message<-x
}
}
}()
for {
select {
case <-isQuit:
delete(onlineClient,addr)
message<-MakeMessage(client,"logout")
return
case <-time.After(time.Second*60):
delete(onlineClient,addr)
message<-MakeMessage(client,"timeout leaved")
return
}
}
}(conn)
}
}
func Manager() {
for {
msg:=<-message
for _,client:=range onlineClient{
client.C<-msg
}
}
}
func SendMessageToClient(client Client,conn net.Conn) {
for x:=range client.C{
conn.Write([]byte(x+"\n"))
}
}
func MakeMessage(client Client,x string) string {
return "["+client.Addr+"]"+client.Name+" "+x
}
Client1 Client2
package main
import (
"net"
"fmt"
"io"
"os"
)
func main() {
conn,err:=net.Dial("tcp","127.0.0.1:8000")
if err!=nil {
fmt.Println(err)
return
}
defer conn.Close()
go func() {
m:=make([]byte,4096)
for {
n,err:=os.Stdin.Read(m)
conn.Write(m[:n])
if err!=nil && err!=io.EOF {
fmt.Println(err)
continue
}
}
}()
m:=make([]byte,4096)
for {
n,err:=conn.Read(m)
fmt.Print(string(m[:n]))
if err!=nil && err!=io.EOF {
fmt.Println(err)
continue
}
}
}