服务器启动方式:
./clock-server -port 8000 &
./clock-server -port 8001 &
./clock-server -port 8002 &
这样就模拟启动了三个城市的服务器
代码:
package main
import (
"flag"
"fmt"
"io"
"log"
"net"
"time"
)
//这里用flag包获取一下端口参数
var port = flag.Int("port", 8000, "listen port: -port 8000")
func init() {
flag.Parse()
}
func main() {
addr := fmt.Sprintf("localhost:%d", *port)
fmt.Println(addr)
listenner, err := net.Listen("tcp", addr)
if err != nil {
log.Fatal(err)
}
for {
conn, err := listenner.Accept()
if err != nil {
log.Print(err)
continue
}
go handleConn(conn) //一个协程处理一个连接
}
}
func handleConn(c net.Conn) {
defer c.Close()
for {
_, err := io.WriteString(c, time.Now().Format("15:04:05\n")) //把时间返回给客户端
if err != nil {
return
}
time.Sleep(1 * time.Second)
}
}
客户端启动方式:go run clock-cli.go NewYork=localhost:8000 Youko=localhost:8001 London=localhost:8002
客户端代码用单一工厂模式创建一个GetClocks对象,用AddCity方法添加城市,用Start()方法启动与服务器的连接请求,每一个城市使用一个协程,主协程使用wg.Wait()等待所以协程返回,然后才从Start()方法返回。代码如下:
package main
import (
"bufio"
"errors"
"fmt"
"log"
"net"
"os"
"strings"
"sync"
"time"
)
type GetClocks struct {
Cities []string //city slice
Addrs []string //city's addr:port
Times []string //city's clock
cnt int //total cities
wg sync.WaitGroup //wait for all query city return
}
//new a struct
func NewGetClocks() *GetClocks {
clocks := new(GetClocks)
clocks.Cities = make([]string, 0)
clocks.Addrs = make([]string, 0)
clocks.Times = make([]string, 0)
return clocks
}
func (clocks *GetClocks) AddCity(city, address string) {
clocks.Cities = append(clocks.Cities, city)
clocks.Addrs = append(clocks.Addrs, address)
clocks.Times = append(clocks.Times, "null")
clocks.cnt++
}
func (clocks *GetClocks) Start() error {
if clocks.cnt != 0 {
for i := 0; i < clocks.cnt; i++ {
clocks.wg.Add(1) //启动协程之前先Add(1)
go func(i int) {
defer clocks.wg.Done() //协程返回时记得Done
var (
conn net.Conn
err error
)
conn, err = net.DialTimeout("tcp", clocks.Addrs[i], 5*time.Second)
if err != nil {
clocks.Times[i] = "connect err!"
log.Printf("Connect to %v, address: %v failed\n",
clocks.Cities[i], clocks.Addrs[i])
return
}
defer conn.Close()
//读取服务器返回的一行,就结束
if clocks.Times[i], err = bufio.NewReader(conn).ReadString('\n'); err != nil {
clocks.Times[i] = "get err!"
log.Printf("%v, address: %v get clocke failed:%v\n", clocks.Cities[i], clocks.Addrs[i], err)
}
}(i)
}
clocks.wg.Wait()
return nil
}
return errors.New("No any city!")
}
//打印取得的各个城市的时间
func (clocks *GetClocks) Display() {
for i, city := range clocks.Cities {
fmt.Printf("%s : %s\n", city, clocks.Times[i])
}
}
//./app NewYork=localhost:8000 youko=localhost:8001 london=localhost:8002
func main() {
clocks := NewGetClocks()
for _, argv := range os.Args[1:] {
city_addr := strings.Split(argv, "=")
clocks.AddCity(city_addr[0], city_addr[1])
}
clocks.Start()
clocks.Display()
}
运行结果:
root@myubuntu:go-websocket# go run clock-cli.go NewYork=localhost:8000 Youko=localhost:8001 London=localhost:8002
NewYork : 23:40:13
Youko : 23:40:13
London : 23:40:13