这段代码出自《Go程序设计语言》(英文版)第254页,一段很简单的代码实现了一个简易的聊天服务器。里面涉及了tcp通讯、输入/输出、使用chan传值等。
//服务器代码
package main
import (
"bufio"
"fmt"
"io"
"log"
"net"
)
func main() {
listener, err := net.Listen("tcp", ":8000")
if err != nil {
log.Fatal(err)
}
fmt.Println("Server listens successfull and gets ready for acceptions")
go broadcaster()
for {
conn, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
fmt.Printf("[%v] connected \n", conn.RemoteAddr())
go handleConn(conn)
}
}
type client chan<- string
var (
entering = make(chan client)
leaving = make(chan client)
message = make(chan string)
)
func broadcaster() {
clients := make(map[client]bool)
for {
select {
case msg := <-message:
for cli := range clients {
cli <- msg
}
case cli := <-entering:
clients[cli] = true
case cli := <-leaving:
delete(clients, cli)
close(cli)
}
}
}
func handleConn(c net.Conn) {
defer c.Close()
ch := make(chan string)
go clientWriter(c, ch)
ch <- "Welcome!\n"
entering <- ch
message <- fmt.Sprintf("[%v] in \n", c.RemoteAddr())
input := bufio.NewScanner(c)
for input.Scan() {
message <- fmt.Sprintf("[%v] say: %v \n", c.RemoteAddr(), input.Text())
}
leaving <- ch
message <- fmt.Sprintf("[%v] out \n", c.RemoteAddr())
fmt.Printf("[%v] disconnected \n", c.RemoteAddr())
}
func clientWriter(c net.Conn, ch <-chan string) {
for msg := range ch {
io.WriteString(c, msg)
}
}
//客户端
package main
import (
"io"
"log"
"net"
"os"
)
func main() {
conn, err := net.Dial("tcp", ":8000")
if err != nil {
log.Fatal(err)
}
go mustCopy(os.Stdout, conn)
mustCopy(conn, os.Stdin)
}
func mustCopy(dest io.Writer, src io.Reader) {
if _, err := io.Copy(dest, src); err != nil {
log.Fatal(err)
}
}