[日常] Go语言圣经-基于select的多路复用习题

练习 8.8: 使用select来改造8.3节中的echo服务器,为其增加超时,这样服务器可以在客户端10秒中没有任何喊话时自动断开连接。

reverb3.go

package main

import (
        "bufio"
        "fmt"
        "log"
        "net"
        "strings"
        "sync"
        "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处理连接
        }
}
/*
1.启动一个goroutine,for死循环让他不能断掉
select语句case判断两个channel
一个是10秒后断掉连接
另一个是接收标准输入后发送过来的channel,接收到值后,启动goroutinue输出

2.for循环接收标准输入,接收到后发送给message的channel
*/
func handleConn(c net.Conn) {
        input := bufio.NewScanner(c)
        var wg sync.WaitGroup
        var message = make(chan string)
        wg.Add(1)
        go func() {
                defer wg.Done()
                for {
                        select {
                        case <-time.After(10 * time.Second):
                                c.Close()
                        case mes := <-message:
                                wg.Add(1)
                                go func(c net.Conn, shout string, delay time.Duration) {
                                        defer wg.Done()
                                        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))
                                        //ch<-struct{}{}

                                }(c, mes, 1*time.Second)

                        }
                }
        }()
        for input.Scan() {
                text := input.Text()
                message <- text
        }

        wg.Wait()
        //cw := c.(*net.TCPConn)
        //cw.CloseWrite()

        c.Close()
}

  

原文地址:https://www.cnblogs.com/taoshihan/p/8995716.html

时间: 2024-10-02 05:05:03

[日常] Go语言圣经-基于select的多路复用习题的相关文章

[日常] Go语言圣经--复数,布尔值,字符串习题

go语言圣经-复数 1.我们把形如a+bi(a,b均为实数)的数称为复数,其中a称为实部,b称为虚部,i称为虚数单位.两种精度的复数类型:complex64和complex128,分别对应float32和float64两种浮点数精度 2.complex函数用于构建复数,real和imag函数分别返回复数的实部和虚部 go语言圣经-布尔型 1.布尔值可以和&&(AND)和||(OR)操作符结合,并且有短路行为 2.&&的优先级比||高 go语言圣经-字符串 1.一个字符串是一

[日常] Go语言圣经--作用域,基础数据类型,整型

go语言圣经-作用域 1.一个声明语句将程序中的实体和一个名字关联,比如一个函数或一个变量 2.一个变量的生命周期是指程序运行时变量存在的有效时间段;声明语句的作用域对应的是一个源代码的文本区域,它是一个编译时的属性 3.句法块是由花括弧所包含;我们可以把块(block)的概念推广到包括其他声明的群组,这些声明在代码中并未显式地使用花括号包裹起来,我们称之为词法块. 4.全局作用域 包级语法域 源文件级的作用域 局部作用域 函数级的作用域 5.从最内层的词法域向全局的作用域查找.内部的会覆盖外部

[日常] Go语言圣经--接口约定习题

Go语言圣经-接口1.接口类型是对其它类型行为的抽象和概括2.Go语言中接口类型的独特之处在于它是满足隐式实现的3.Go语言中还存在着另外一种类型:接口类型.接口类型是一种抽象的类型4.一个类型可以自由的使用另一个满足相同接口的类型来进行替换被称作可替换性(LSP里氏替换) 练习 7.1: 使用来自ByteCounter的思路,实现一个针对对单词和行数的计数器.你会发现bufio.ScanWords非常的有用. package main import ( "bufio" "f

Go语言圣经-Panic异常,Recover捕获异常习题

Go语言圣经-Panic异常1.当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer 机制)2.不是所有的panic异常都来自运行时,直接调用内置的panic函数也会引发panic异常:panic函数接受任何值作为参数.3.由于panic会引起程序的崩溃,因此panic一般用于严重错误,如程序内部的逻辑不一致,对于大部分漏洞,我们应该使用Go提供的错误机制,而不是panic4.为了方便诊断问题,runtime包允许输出堆栈信息 Go语言圣经-Reco

[日常] Go语言圣经-匿名函数习题2

练习5.13: 修改crawl,使其能保存发现的页面,必要时,可以创建目录来保存这些页面.只保存来自原始域名下的页面.假设初始页面在golang.org下,就不 要保存vimeo.com下的页面. package main import ( "fmt" "io" "io/ioutil" "links" "log" "net/http" "net/url" "

[日常] Go语言圣经-指针对象的方法-bit数组习题2

练习 6.3: (*IntSet).UnionWith会用|操作符计算两个集合的交集,我们再为IntSet实现另外的几个函数IntersectWith(交集:元素在A集合B集合均出现),DifferenceWith(差集:元素出现在A集合,未出现在B集合),SymmetricDifference(并差集:元素出现在A但没有出现在B,或者出现在B没有出现在A). *练习6.4: 实现一个Elems方法,返回集合中的所有元素,用于做一些range之类的遍历操作. 练习 6.2: 定义一个变参方法(*

[日常] Go语言圣经--接口约定习题2

练习 7.3: 为在gopl.io/ch4/treesort (§4.4)的*tree类型实现一个String方法去展示tree类型的值序列. package main import( "fmt" "bytes" ) func main(){ //定义数组 arr:=[...]int{6,2,1,3,4,5} var t *tree for i:=0;i<len(arr);i++{ t=add(t,arr[i]) } //t1:=Sort(arr[:],t)

[日常] Go语言圣经--示例: 并发的Clock服务习题

练习 8.1: 修改clock2来支持传入参数作为端口号,然后写一个clockwall的程序,这个程序可以同时与多个clock服务器通信,从多服务器中读取时间,并且在一个表格中一次显示所有服务传回的结果,类似于你在某些办公室里看到的时钟墙.如果你有地理学上分布式的服务器可以用的话,让这些服务器跑在不同的机器上面:或者在同一台机器上跑多个不同的实例,这些实例监听不同的端口,假装自己在不同的时区.像下面这样: $ TZ=US/Eastern ./clock2 -port 8010 & $ TZ=As

[日常] Go语言圣经--示例: 并发的Echo服务

最简单的回声服务器: 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