// clock1 是一個定期報告時間的 TCP 伺服器 package main import ( "io" "log" "net" "time" ) func main() { listener, err := net.Listen("tcp", "localhost:8000") if err != nil { log.Fatal(err) } for { conn, err := listener.Accept() if err != nil { log.Print(err) //例如,連線中止 continue } handleConn(conn) // 一次處理一個連線 } } func handleConn(c net.Conn) { defer c.Close() for { _, err := io.WriteString(c, time.Now().Format("15:04:05n")) if err != nil { return //例如,連線斷開 } time.Sleep(1 * time.Second) } }Listen 函數建立一個 net.Listener 物件,它在一個網路埠上監聽進來的連線,這裡是 TCP 埠 localhost:8000。監聽器的 Accept 方法被阻塞,直到有連線請求進來,然後返回 net.Conn 物件來代表一個連線。
$ go build gopl.io/ch8/clockl
$ ./clock1 &
$ nc localhost 8000
13:58:54
13:58:55
13:58:56
13:58:57
^C
// netcat1是一個唯讀的 TCP 用戶端程式 package main import ( "io" "log" "net" "os" ) func main() { conn, err : = net.Dial("tcp", "localhost:8000") if err != nil { log.Fatal(err) } defer conn.Close() mustCopy(os.Stdout, conn) } func mustCopy(dst io.Writer, src io.Reader) { if _, err := io.Copy(dst, src); err != nil { log.Fatal(err) } }這個程式從網路連線中讀取,然後寫到標準輸出,直到到達 EOF 或者岀錯。mustCopy 函數是這一節的多個例子中使用的一個實用程式。在不同的終端上同時執行兩個用戶端,一個顯示在左邊,一個在右邊:
$ go build gopl.io/ch8/netcat1
$ ./netcat1
13:58:54 $ ./netcat1
13:58:55
13:58:56
^C
13:58:57
13:58:58
13:58:59
^C
$ killall clock1
for { conn, err := listener.Accept() if err != nil { log.Print(err) //例如,連線中止 continue } go handleConn(conn) // 並行處理連線 }現在,多個用戶端可以同時接收到時間:
$ go build gopl.io/ch8/clock2
$ ./clock2 &
$ go build gopl.io/ch8/netcat1
$ ./netcat1
14:02:54 $ ./netcat1
14:02:55 14:02:55
14:02:56 14:02:56
14:02:57 ^C
14:02:58
14:02:59 $ ./netcat1
14:03:00 14:03:00
14:03:01 14:03:01
^C 14:03:02
^C
$ killall clock2