像闪电一样快速扫描全网的IP地址

新开一个Go编程系列,主要讲Go语言的高级编程技术,希望能像《Go并发编程指南》一样形成一个系列,不要断更。

先前将近二十年的编程开发中,涉及到网络编程,主要还是使用标准库的网络库,无论是C#、Java、Go,编写的都是都UDP或者TCP的网络程序,主要在应用层做一些研发工作,包括微服务框架rpcx,来到百度基础网络部之后,主要负责黑盒的网络监控和告警,接触了很多底层的网络编程的技术,以及为了性能和大规模的探测做了各种的技术探索,从TCP/IP 二层三层通讯到机房内各种架构和层级连通,从vxLan到BGP,从内网、专线到自治系统,从25G网卡到100G网卡,从200G交换机到400G、800G交换机,从光纤劣化到长途链路自检和复用,从lldp到telemetry,很多概念我都是第一次接触到,所以感觉这两年来我虽然基础架构的工作做的少了,但是很好的弥补了我网络知识的确实,反而对我基础架构工作网络相关的知识做了弥补,很多以前不太理解的知识现在豁然开朗了。

我希望把我的知识沉淀下来,所以开一个《Go高级网络编程》系列,对网络编程的知识做一个总结,当然这些是通用的网络知识,不会涉及公司内部的业务逻辑。

虽然大致章节我已经确定,我还是挑一些有深度的章节先分享出来,TCP/UDP/ICMP等编程虽然也有很多细节可挖掘的地方,但是毕竟大部分的知识大家都已经了解了,这些章节放在最后再分享。

这一篇是使用gopacket库编程的一部分,主要是通过手工构造数据链路层、网络层、传输层的包,实现扫描全网(示例中是中国大陆的) ipv4的IP地址,看看对应的网络是否可达。 首先我们需要知道全网的IP地址,其实我们可以使用fping探测这些IP是否连通,然后我们自己基于ICMP快速扫描这些IP,找出全网活跃的IP地址,最后我们使用tcp scan的方式扫描全网的IP,甚至你可以扫描公网上暴露的Redis实例。

阅读全文

机智!生抠 map的哈希函数

前一段时间我尝试为orcaman/concurrent-map实现泛型的支持时,遭遇到为任意类型计算哈希值的问题,现在这个库也自己实现了泛型支持,你也可以看到它的哈希也没有好的办法,只能提供出一个函数对象让用户自己实现。当然你也可以参考[cornelk/hashmap/blob/36b3b9c2b7ec993f1ef12a6957d45826aca726e6/util_hash.go#L49)中的实现,但是它的实现既不全面也不高效?

我们经常会在一些场景,比如特定的数据结构、cache等场景中使用这样一个哈希函数,那么如何为任务类型实现一个优雅高效的hash函数呢?其实Go运行时中map中就实现了。回想一下内建的map是不是支持泛型的?它的key可以是comparable类型(包括接口类型),内部实现中会把此类型的key计算一个哈希值,能不能吧它的hash函数拿出来使用?很遗憾,Go官方并没有想暴露出来这样的hasher的想法,它的代码也是不容易抽取整理成一个hasher函数。

今天看到一篇文章Hacking Go's Runtime with Generics,提供了一种方法,脑洞大开。没看之前确实没想到,看到之后才发觉这么简单有效,接下来我翻译了这么文章,赶快学习吧。

阅读全文

一些关于时间和定时任务的库

避免重复发明轮子。如果有一些好用的库,我们就直接使用就好了,没必要做一些重复的工作,如果这些库不能满足需求,不妨提交pull request或者clone 它们,提升它们,优化它们,当前前提是你得知道它们。

这篇文章给大家介绍一些关于时间和类似linux cron功能的定时任务库。

阅读全文

零拷贝技术第一篇:综述

零拷贝(zero copy)在一些语境下指代的意思有所不同,本文讲的零拷贝就是大家常说的,通过这个技术让CPU释放出来不去执行内存中数据拷贝的功能,或者避免不必要的拷贝,所以说零拷贝不是没有数据的拷贝(复制),而是广义上讲的减少和避免不必要的数据拷贝,可以用来节省CPU使用和内带宽等,比如通过网络高速传输文件、实现网络proxy等等,零拷技术可以极大的提高程序的性能。

阅读全文

还咋优化?我是说Go程序

Go语言是一个极容易上手的语言,而且Go程序的优化套路基本上被大家莫得清清楚楚的,如果你有心,可以在互联网上搜出很多Go程序优化的技巧,有些文章可能只介绍了几个优化点,有些文章从CPU的架构到Slice预分配,再到通过pprof找性能的瓶颈点等等全面介绍Go程序的优化,所以说可见的手段基本上被大家摸得门清,最近老貘出了一道题,如下所示,可以看到大家对Go语言的优化已经摸的多深了。

阅读全文

Rust 并发编程实战课

Rust 越来越得到广泛的应用,尤其对于追求性能的系统编程领域,最近还正式进入了Linux 内核的主干,并预计在 6.1 版本中正式使用。

Rust 虽然设计理念独树一帜,性能也是那么的优秀,但是学习起来并不简单,学习曲线很陡。同时由于Rust不像Go语言一样,不受某一家公司的控制,看起来在开源方面貌似很“Open”,所以也得到了广大开发者的青睐,贡献了许多库,不乏高质量的库,甚至比标准库的质量和使用率还高,这也带来了一些问题。其他语言,比如Go语言,它的标准库相当的优秀,比如一堆优秀高质量的并发原语,在开发者在开发并发程序的时候,需要同步控制和任务编排时,脑海中第一选择就是标准库的并发原语,实在找不到合适的并发原语才去找第三方的库。但是Rust不一样,虽然标准库也提供了一些优秀的并发原语,但是限于语言的特性,使用起来相当的复杂,也有很多第三方的库提供性能更好或者特性更多或者更易使用的功能,所以在使用Rust开发并发程序的时候,很多开发者对并发逻辑的控制无从下手,或者有“选择困难症”,所以我专门开了一个序列,准备系统的介绍 Rust的并发编程的知识,通过一百多个简短而明确的例子,全面介绍Rust的并发编程和相关库的使用:rust programming via rust .

阅读全文

十多年了,这个最容易犯错的Go语法终于要改了

Go 语言中你最容易犯错的语法是什么?很多人可能都有不同的答案,但是最多的答案之一就是 for 循环中变量的使用问题了。即使是 Go 团队的开发者,我也曾看到他们提交的代码犯过这种错误,更不用说其他的 Go 开发者了,比如this problem at Let’s Encrypt,几乎每个Go开发者都犯过这个错误,这种类型的错误已经在我的心里留下了阴影,每次写for循环我都心头一紧,经常使用局部变量shade一下循环变量,即使没有问题。

阅读全文