开发者
2022-04-07
BNF,Backus-Naur Form,或者 Backus Normal Form,巴科斯范式
用来准确地描述一种计算机语言的语法规则,所以可以理解成是 “语言的语言”。
约翰·巴科斯(美国)首次在 ALGOL 58 中实现巴科斯范式。彼得·诺尔(丹麦)在 ALGOL 60 之中,进一步发展它的概念并将它的符号加以简化,称其为巴科斯范式(Backus Normal Form)。但高德纳主张应称为巴科斯-诺尔范式(Backus–Naur Form),因为它不算是一种正规形式(Normal Form)。
BNF 有两种常见变体:
- ABNF,扩充巴科斯范式
- EBNF,扩展巴科斯范式
不用深究 BNF,EBNF,ABNF,或者什么 xBNF 之间到底有什么区别,在需要开发语法解析器之前,只用知道这些是现在最主流的语法语言就行了。
这篇文章讨论的就是 Internet 领域常用的 ABNF。
(ABNF)它是由第68号互联网标准定义的,也就是RFC 5234,经常用于互联网工程任务组(IETF)通信协议的定义语言。
规则
ABNF 语法描述就是一组规则,每个规则分成规则名称、规则说明两部分。
PS:规则说明可以引用其他的规则。
拿 RFC#822 Internet Message Format 中的例子:
date-time = [ day-of-week "," ] date FWS time [CFWS]
day-of-week = ([FWS] day-name) / obs-day-of-week
day-name = "Mon" / "Tue" / "Wed" / "Thu" /
"Fri" / "Sat" / "Sun"
date = day month year
PS:这里只是截取的部分,没有列出来的规则在别处声明。
参考资料与拓展阅读
开发者 英语
2022-04-02
开发者想必都有耳闻,过去一两年间,因为一些美国政治风波的影响,各大社区都被政治正确问题所困扰,然后有一些相关改名的操作。
PS: 连黑人牙膏(高露洁旗下)都改名 “好来牙膏” 了。
最著名的可能就是 GitHub 中的默认主干分支从 master 改成 main,然后很多项目宣布将主从表述由 master/slave 改成 primary/replica,黑名单 Blacklist 改叫 Denylist 或者 Blocklist。
我最近听说有个叫包容性命名促进会的组织(Inclusive Naming Initiative)。
https://inclusivenaming.org/
他们列了一个清单,将开发过程中常用的一些有冒犯性的词,按照冒犯级别分三类,然后还给出来一些他们建议的替换词。
开发者 千年虫
2022-01-28
前些天应该都看过微软 Exchange Server 开发者跨年改 BUG 的新闻了吧 (相关链接)。
Exchange Server 的邮件过滤器采用了 yymmddHHMM
格式的时间,存储在 long
类型字段中。
PS: 微软的 C++ Compiler 会将 long 当做 32 位 int。
32 位有符号整形能够表达的范围:[$-2^{31}$, $2^{31} - 1$],也就是 [-2147483648, 2147483647]。
到了 2022 年,就会超出范围,比如 2022-01-01 12:00:00
, 会被存储为 2201011200
,会超出 signed int 的表达范围。
2147483647
2201011200 # 超出
可能有一些系统采用 int 类型存储 yymmdd + 4 位数字做编号的方式,比如 2101011234。
相同的原因,到了 2022 年,就行不通了。
2147483647
2201011234 # 超出
最好的办法是改成 long long
, 或者 unsigned int
。
PS: Linux 下的 C/C++ 编译器——GCC、CLang/LLVM 都是将 long 当做是 64 位。
参考资料与拓展阅读
- 微软文档,Data Type Ranges
Docs > Microsoft C, C, and Assembler > C language > C++ language reference > Built-in types > Data type ranges
- 微软文档,C and C++ Integer Limits
Docs > Microsoft C, C, and Assembler > C language > C language reference > Elements of C > C constants > C integer constants > C and C integer limits
- 人们说 32 位、64 位时,到底是在说啥
开发者 Curl
2021-11-28
Here is a command I use often while measuring why an HTTP request is taking too long:
curl -L -w "time_namelookup: %{time_namelookup}
time_connect: %{time_connect}
time_appconnect: %{time_appconnect}
time_pretransfer: %{time_pretransfer}
time_redirect: %{time_redirect}
time_starttransfer: %{time_starttransfer}
time_total: %{time_total}
" https://example.com/
Here is the same command written as a one-liner, so that I can copy it easily from this page with a triple-click whenever I need it in future:
curl -L -w "time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_pretransfer: %{time_pretransfer}\ntime_redirect: %{time_redirect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" https://example.com/
Here is how the output of the above command typically looks:
$ curl -L -w "namelookup: %{time_namelookup}\nconnect: %{time_connect}\nappconnect: %{time_appconnect}\npretransfer: %{time_pretransfer}\nstarttransfer: %{time_starttransfer}\ntotal: %{time_total}\n" https://example.com/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
...
</html>
time_namelookup: 0.001403
time_connect: 0.245464
time_appconnect: 0.757656
time_pretransfer: 0.757823
time_redirect: 0.000000
time_starttransfer: 0.982111
time_total: 0.982326
In the output above, I have omitted most of the HTML output and replaced the omitted part with ellipsis for the sake of brevity.
The list below provides a description of each number in the output above. This information is picked straight from the manual page of curl 7.20.0. Here are the details:
time_namelookup
: The time, in seconds, it took from the start until the name resolving was completed.
time_connect
: The time, in seconds, it took from the start until the TCP connect to the remote host (or proxy) was completed.
time_appconnect
: The time, in seconds, it took from the start until the SSL/SSH/etc connect/handshake to the remote host was completed. (Added in 7.19.0)
time_pretransfer
: The time, in seconds, it took from the start until the file transfer was just about to begin. This includes all pre-transfer commands and negotiations that are specific to the particular protocol(s) involved.
time_redirect
: The time, in seconds, it took for all redirection steps include name lookup, connect, pretransfer and transfer before the final transaction was started. time_redirect shows the complete execution time for multiple redirections. (Added in 7.12.3)
time_starttransfer
: The time, in seconds, it took from the start until the first byte was just about to be transferred. This includes time_pretransfer and also the time the server needed to calculate the result.
time_total
: The total time, in seconds, that the full operation lasted. The time will be displayed with millisecond resolution.
An important thing worth noting here is that the difference in the numbers for time_appconnect
and time_connect
time tells us how much time is spent in SSL/TLS handshake. For a cleartext connection without SSL/TLS, this number is reported as zero. Here is an example output that demonstrates this:
$ curl -L -w "time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_pretransfer: %{time_pretransfer}\ntime_redirect: %{time_redirect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" http://example.com/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
...
</html>
time_namelookup: 0.001507
time_connect: 0.247032
time_appconnect: 0.000000
time_pretransfer: 0.247122
time_redirect: 0.000000
time_starttransfer: 0.512645
time_total: 0.512853
Also note that time_redirect
is zero in both outputs above. That is because no redirection occurs while visiting example.com. Here is another example that shows how the output looks when a redirection occurs:
$ curl -L -w "time_namelookup: %{time_namelookup}\ntime_connect: %{time_connect}\ntime_appconnect: %{time_appconnect}\ntime_pretransfer: %{time_pretransfer}\ntime_redirect: %{time_redirect}\ntime_starttransfer: %{time_starttransfer}\ntime_total: %{time_total}\n" https://susam.in/blog
<!DOCTYPE HTML>
<html>
...
</html>
time_namelookup: 0.001886
time_connect: 0.152445
time_appconnect: 0.465326
time_pretransfer: 0.465413
time_redirect: 0.614289
time_starttransfer: 0.763997
time_total: 0.765413
When faced with a potential latency issue in web services, this is often one of the first commands I run several times from multiple clients because the results form this command help to get a quick sense of the layer that might be responsible for the latency issue.