重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
我想的事为每个client fd开两个goroutine,一个recv,一个send。同时还有加2个channel,一个用于recv routine向逻辑主线程传送收到的数据,一个用于逻辑主线程向send goroutine传送待发送的数据,是这样的么?
站在用户的角度思考问题,与客户深入沟通,找到新津县网站设计与新津县网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:做网站、成都做网站、企业官网、英文网站、手机端网站、网站推广、主机域名、网络空间、企业邮箱。业务覆盖新津县地区。
实际上需要 3 个 goroutine,一个 read,一个 send,还有一个 handle。
read goroutine 读,然后写入 recevice chan。
write goroutine 把 send chan 的东西写。
handle goroutine 是 conn 的主要处理逻辑,负责把 recevice chan 的东西读出来 call 业务逻辑。
业务逻辑中要写数据就直接写入 send chan。
这样就可以保证,业务逻辑的读写都是在 handle goroutine 上处理,而避免 race 产生。
如果需要定时任务(比如心跳),就在 handle goroutine 上加上一个 timer.C;
如果需要 goroutine 下发任务,在 handle goroutine 增加一个 task chan,hanlde 收到 task 后处理业务;
如果需要输出结果,那就增加 result chan,业务逻辑把数据输出即可。
----------------------------
还有,如果我开2个goroutine的话,client断开连接了,假设recv goroutine先发生err并且close(fd),那在send goroutine中该如何处理呢?有可能不应该这样处理,那应该怎么处理呢?
如果 net.Conn Close() 了,不论 Read() 阻塞还是 Write() 阻塞都会立即收到 err 返回。
一般来说,Write() 是不可能主动知道连接断开的,除非是 SetDeadline() 猜测对方断掉了,指定时间内没有写成功就认为是断开。Read() 是可以主动收到对方发来的断开(TCP FIN),但也没办法知道异常的断开(当然也可以设置超时)。
无论是谁,是确实收到 FIN 还是 Deadline 猜测断开,只要 Close() 大家就知道连接断开了。
handle goroutine 还有一个用处就是:你的程序主动结束的时候,能正确的 close conn,让对方知道你是真的断开了,而不用去猜。
个人理解的channel超时处理思路分享,若有错误或者不足,请联系我:qq 869329877
主程序通过go timeout()挂起一个协程,在timeout方法里面利用select来监控逻辑处理的变化,如果请求时间过长或者连接到其他服务比如grpc、mysql等服务中断导致的请求时间过长,则直接超时,超时要返回定义的管道数据结果,否则程序会报错。
设置时间间隔为5秒 如果get不到就断开连接,post方法类似 都在client里设置http的超时时间
timeout := time.Duration(5 * time.Second)
client := http.Client{
Timeout: timeout,}
client.Get(url)
上一节中,我们为每个连接都创建了一个goroutine来读取其中的消息,现在我们将这个读取消息的方法实现一下。
我们在application目录下新建controllers目录,并在其中创建一个MessageController.go文件。
首先我们新建一个MessageController的结构体,内容如下
这个结构体包括两个内容,一个是我们将连接放在数组之后,返回的索引,另一个是连接本身.
这个是具体的方法。
我们首先设置了一下读消息的大小、超时时间以及超时后需要的操作。
超时时间如果设置为0,那么就是永不超时。之前在这里直接写0,被告知需要传一个time.Time类型的数据。最终谷歌后才得到了这个值time.Time{}为"0001-01-01 00:00:00 +0000 UTC"。
我们将用户手法消息的内容定义为一个结构体,然后将用户的订阅信息的json通过json.unmarshal转换成这个结构体。
之后的switch操作与我们在Swoole中的操作基本雷同,在查询到login之后,调用service中 的login方法来进行注册。
下一节中我们再介绍具体的注册逻辑。