最简单的回声服务器:
package main
import (
"io"
"net"
"log"
)
func main() {
listener, err := net.Listen("tcp", ":8040")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err) // e.g., connection aborted
continue
}
go handleConn(conn) //新建goroutines处理连接
}
}
func handleConn(c net.Conn) {
io.Copy(c, c) // NOTE: ignoring errors
c.Close()
}
原理:
1.io.Copy()方法 func Copy(dst Writer, src Reader) (written int64, err error)
2.net.Conn类型 type Conn interface { Read(b []byte) (n int, err error) Write(b []byte) (n int, err error) ... } 一个类型如果拥有一个接口需要的所有方法,那么这个类型就实现了这个接口
3.io.Writer type Writer interface { Write(p []byte) (n int, err error) } 4.io.Reader type Reader interface { Read(p []byte) (n int, err error) }
升级版,每条连接一个goroutine,每个goroutine中分出多个输出goroutine
package main
import (
"bufio"
"fmt"
"log"
"net"
"strings"
"time"
)
func main() {
listener, err := net.Listen("tcp", ":8040")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err) // e.g., connection aborted
continue
}
go handleConn(conn) //新建goroutines处理连接
}
}
func handleConn(c net.Conn) {
input := bufio.NewScanner(c)
for input.Scan() {
go echo(c, input.Text(), 1*time.Second)
}
// NOTE: ignoring potential errors from input.Err()
c.Close()
}
func echo(c net.Conn, shout string, delay time.Duration) {
fmt.Fprintln(c, "\t", strings.ToUpper(shout))
time.Sleep(delay)
fmt.Fprintln(c, "\t", shout)
time.Sleep(delay)
fmt.Fprintln(c, "\t", strings.ToLower(shout))
}
1.fmt.Fprintln() func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
2.bufio.NewScanner() func NewScanner(r io.Reader) *Scanner func (s *Scanner) Scan() bool func (s *Scanner) Text() string
也用到了大量的7.3节 实现接口的条件