Hello World 应该是每一位程序员的启蒙程序,出自于 Brian Kernighan 和 Dennis Ritchie 的一代经典著作 The C Programming Language。
// hello.c
#include <stdio.h>
int main() {
printf("hello, world\n");
return 0;
}
这段代码我想大家应该都太熟悉了,熟悉到可以默写出来。虽然是非常简单的代码,但是如果细究起来,里面却隐含着很多细节:
#include <stdio.h>
和#include "stdio.h"
有什么区别?stdio.h
文件在哪里?里面是什么内容?- 为什么入口是
main
函数?可以写一个程序入口不是main
吗? main
的 int 返回值有什么用?是谁在处理main
的返回值?printf
是谁实现的?如果不用printf
可以做到在终端中打印字符吗?
BitTorrent 想必大家应该都不陌生,中文名叫做“种子”。
“种子”到底是什么?我一直不太清楚。在写这个项目之前,我对“种子”的认识停留在使用层面。
当我想找一个资源的时候,我会搜索 xxx 种子
,一般会在一些非常不知名的小网站里面获取到以 .torrent
结尾的种子文件,然后使用迅雷或者 uTorrent 这样的下载器来下载。
如果迅雷有一点速度,哪怕几 kb,那么大概率我充个会员就搞定了。这个软件就是这么的恶心,不用有时候又没办法,像极了人生。
其他下载器比如 uTorrent 的话就一切随缘了,有些资源非常快,有些资源非常慢,有些一开始慢后来快。
这些问题是怎么回事?有没有改进的办法?在读 Jesse Li 的 Building a BitTorrent client from the ground up in Go 之前,我从没想过。
2020.10.09 更新:最近收到了一封官方的邮件,希望我把仓库隐藏起来,避免新同学直接 copy 我的代码。既然是来自官方的要求,自然毫不犹豫地配合。仓库和我归档的 Winter 2020 课程现在都不可见了,想要学习这门课程的同学可以直接去官方站点学习,祝大家学习愉快~
CS107e 全称为 CS107e: Computer Systems from the Ground Up,是斯坦福大学的一门计算机课程,也是我目前为止发现的最好的关于硬件、底层和 C 的一门课程。
在课程学习过程中,我们会一步一步地从头开始使用 C 为树莓派开发一个操作系统核心。
根据官方的介绍,这门课程主要学习目标有两个:
- To understand how computers represent information, execute programs, and control peripherals. 理解计算机是怎样存储信息,执行程序以及控制外围设备。
- To master command-line programming tools and the C programming language. 掌握命令行编程工具和 C 语言。
Shell 对程序员来说是必不可少的生产力工具。
$ figlet <<< "Hello Shell"
_ _ _ _ ____ _ _ _
| | | | ___| | | ___ / ___|| |__ ___| | |
| |_| |/ _ \ | |/ _ \ \___ \| '_ \ / _ \ | |
| _ | __/ | | (_) | ___) | | | | __/ | |
|_| |_|\___|_|_|\___/ |____/|_| |_|\___|_|_|
之前因为业务原因需要爬取一批斗鱼主播的相关数据,在这过程中我发现斗鱼使用了一种很有意思的反爬技术,字体反爬。
打开任何一个斗鱼主播的直播间,例如 这个主播,他的关注人数数据显示在右上角:
斗鱼在关注数据这里使用了字体反爬。什么是字体反爬?也就是通过自定义字体来自定义字符与渲染图形的映射。比如,字符 1 实际渲染的是 9,那么如果 HTML 中的数字是 111,实际显示就是 999。
在这种技术下,传统的通过解析 HTML 文档获取数据的方式就失效了,因为获取到的数据并不是真实数据。
很早之前我就想写一个 GBA 模拟器,因为小时候的 GBA 游戏给我留下了深刻的印象。
口袋妖怪、孤岛求生、牧场物语这些 GBA 的经典游戏,在那个时候还玩着小霸王的我眼中,无异于打开了新世界的大门,原来游戏可以这样的有趣。
因为对 GBA 的喜欢,所以有了编写一个 GBA 模拟器的想法。看过一些资料以后,我决定从最简单的 CHIP-8 开始练手。CHIP-8 是一个功能完整的平台,可以运行多个游戏,同时它的设计又非常简单,很适合新手入门。
从我接触计算机开始到现在 Sublime 一直是我的主力编辑器,现代化的 UI、流畅的速度以及众多的插件,特别是各种开箱即用的特性,让他一直默默成为我的生产力助手。
我尽量避免使用各种 IDE,除非万不得以,有些工作不使用配套的工具十分麻烦,比如苹果的 XCode 和谷歌的 Android Studio。如果做 Android/iOS 开发,不用这些工具当然可以,但是绝对是不推荐的方案。第三方工具永远不会有官方的工具更新的快,同时,各种教程资料也不会针对第三方工具,一旦遇到问题只能靠自己解决,这个时间投入,是非常不值得的。
幸好我的主要技术栈都不需要 IDE,JS/HTML/CSS, C, Go 这些语言 IDE 当然可以有些帮助,但是和 IDE 的臃肿卡顿比起来,这些帮助就显得不重要了。
1976 年以前,所有的加密都是如下方式:
- A 使用某种规则对信息进行处理
- B 使用同样的规则对处理过的信息进行复原
这个方式很好理解,不论是非常简单的 ROT13 还是目前广泛使用的 AES,都是这种对称加密方式。
但是这种方式有一个巨大的缺点,那就是 A 需要将对信息进行处理的规则(也就是秘钥)告诉给 B。怎样安全地传输秘钥就成了一个非常棘手的问题。
那么存不存在一种方式,加密和解密使用不同的秘钥,彻底规避掉传输秘钥的问题?
答案是存在的,感谢数学家和计算机科学家,RSA 就是这样一种非对称加密方式,也就是:
- 使用算法可以生成两把钥匙 A 和 B
- 使用 A 加密的信息,使用 B 可以解开
- 使用 B 加密的信息,使用 A 可以解开
日常使用中,我们把一把作为公钥,公开发布。一把作为私钥,自己保留。这样,任何人都可以使用我们的公钥加密信息发给我们,我们则可以使用自己的私钥解开。
只要把私钥保存好,这个通信系统就非常安全。
之前用 Go 编写过一个简单的服务器和客户端,用来测试 Go 的 HTTP 性能,无意中发现了一个奇怪的问题。
在我的 Mac 上客户端程序会非常稳定地遇到 Connection Reset 的错误,让人一头雾水。
图片是大部分网页的重要组成部分,一般情况下,我们不会太关注这方面的问题,需要显示图片直接一个 img
标签搞定。
但实际上,无论是对于提高加载速度,还是对于优化用户体验,优化图片都是一个重要的手段。
图片优化分成两个方面:
第一,图片压缩。在保证视觉效果的情况下,减少图片的体积。这个很有效,1M 和 100K 的图片,肉眼看起来几乎差不多,但却省了 90% 的流量,大大提高了加载速度。
第二,响应式图片。根据客户端的情况,选择最合适的图片返回给用户。用户是一个 500px 的设备,那么返回 1000px 的图给他就是浪费。
我们先来看图片压缩。