-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Golang:为了实现 UDPping 而产生的问题与解惑记录 #19
Comments
一. net.conn没有显式关闭 这一点对于这个程序来说没什么影响。但是如果是对于一直运行的server的话,就会造成资源泄露。 而且golang也提供了defer,所以在创建conn的语句后加上 |
二. goroutine泄露 这个程序运行错误的罪魁祸首就是它了。 首先得了解一下 goroutine+closure 的组合。这份代码里实际上就是这样一个模式:匿名goroutine里闭包了channel类型的ch。可以认为闭包是一个结构体,一个字段指向执行函数,一个字段指向变量ch(且不再改变)。 当我们没有给c设置deadline的时候,c.Read是会一直阻塞住的,直到接收到一个完整的datagram。那么当 server 端第一次丢弃udp包后,对应的接收 goroutine A 的c.Read就会一直阻塞,直到超时,然后执行下一次循环。于是乎,又新启了一个goroutine B 进行 c.Read ,并且阻塞在read waiter queue中,排在前一个goroutine A之后。 导致的结果就是,本该由B接收的udp包,被A给读取了。而goroutine A形成的闭包里的ch早已不是如今select里的ch了,因为我用的是 所以当我们编写goroutine的时候,一定要考虑好goroutine的退出条件是否可以达到,避免造成 goroutine 泄露。 因为一开始没有头绪,还尝试了通过 pprof 来分析的方法。但是由于我这个程序循环了十次,时间太短了吧,所以得到的 cpu profile sample 数量都是 0. |
修改后的版本:https://gist.github.com/wisecsj/7fb5148c40f539ba0b1725c9adbb30d5 运行截图:
可能很多人奇怪为什么它的参数类型是time.Time, 而不是 time.Duration。其实一开始它函数名为 SetTimeout ,参数也的确是 Duration。 但是后来修改过来了,具体原因可以到官方 golang issues 里去看。 我的理解是:当参数指定的time.Time到了,那么当前与特定net.conn挂钩的read和write操作都会返回错误(net.Error,并且Timeout()为true)。但是不影响之后的读写操作,所以如果需要实现Timeout的功能,需要循环设置。 |
UDPping作业来自于《计算机网络-自顶向下方法(原书第6版)》
具体作业要求可见:https://github.com/wisecsj/Computer-Networking-A-Top-Down-Approach-NOTES
大致来讲,其实本质就是一个udp server和client进行通信,然后server随机丢包来模拟ping包的丢失
由于我一开始并不知道 method的存在(还好不知道,不然应该没有这篇blog了,hh)。后面也会有对这个method的理解笔记。
那么不用SetReadDeadline,需要考虑的是什么呢?
因为我们需要计算丢包率,所以需要识别一个包的接收是否timeout了.显然想到了利用time.After + select 来实现。
我的第一版实现:https://gist.github.com/wisecsj/cde649a32001a9186586a899002b944e
The text was updated successfully, but these errors were encountered: