Go语言圣经 - 第8章 Goroutines 和 Channels - 8.3 示例:并发的Echo服务

第8章 Goroutines 和 Channels

Go语言中的并发程序可以用两种手段来实现:goroutine 和 channel,其支持顺序通信进程,或被简称为CSP,CSP是一种并发编程模型,在这种并发编程模型中,值会在不同运行实例中传递,第二个手段便是多线程共享内存

8.3 示例:并发的Echo服务

上一节中clock1服务器中,每一个连接都会创建一个goroutine。现在我们创建一个echo服务器,它的每个连接会有多个Goroutine。大多数echo会返回它们读取到的内容,就下下面这个函数一样

func handleConn(c net.Conn) {
	io.Copy(c,c)
	c.Close()
}

现在我们让echo服务器模拟一个真实的”回响“”也就是随着时间推移,返回值由大写变为小写再到消失

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))
}
func handleConn(c net.Conn) {
	input := bufio.NewScanner(c)
	for input.Scan() {
		echo(c,input.Text(), 1*time.Second)
	}
	c.Close()
}

我们还得升级一下客户端程序

func main() {
	conn, err := net.Dial("tcp", "localhost:8000")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	go mustCopy(os.Stdout, conn)
	mustCopy(conn, os.Stdin)
}

现在我们运行一下,当main goroutine 从标准输入获取内容并将其发送给服务器时,另一个goroutine 会读取并答应服务端的响应,当main goroutine结束时,其它goroutine也会结束

下面这个会话中,客户端的输入是左对齐的,服务端的响应会用缩进来表示,客户端会向服务端喊三次话

 ./netcat2
Hello?
    HELLO?
    Hello?
    hello?
Is there anybody there?
    IS THERE ANYBODY THERE?
Yooo-hooo!
    Is there anybody there?
    is there anybody there?
    YOOO-HOOO!
    Yooo-hooo!
    yooo-hooo!
^D
$ killall reverb1

但是注意,上述的客户端喊话和服务端回话稍显混乱(刚开始客户端喊了好几次,服务都未回复,后来客户端不再喊话,服务端却回复了好多次,感觉两个不在一个频道)那是因为回响不够,我们使用go关键字怎加goroutines

func handleConn(c net.Conn) {
	input := bufio.NewScanner(c)
	for input.Scan() {
		go echo(c,input.Text(), 1*time.Second)
	}
	c.Close()
}

go 后跟的函数的参数会在go语句自身执行时被求值,因此input.Text()会在main goroutine中被求值,现在回想是并发并且会按时间来覆盖掉其它响应了

./netcat2
Is there anybody there?
    IS THERE ANYBODY THERE?
Yooo-hooo!
    Is there anybody there?
    YOOO-HOOO!
    is there anybody there?
    Yooo-hooo!
    yooo-hooo!
^D
$ killall reverb2

不仅在处理多个客户的请求时可以使用并发,在处理单个用户请求时也可以,就像上面的用法,但是可能存在安全隐患,所以需要慎重考虑,关于安全性我们接下来会讨论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值