Luyu Huang's Tech Blog

2020 Annual Summary

At the beginning of 2020, no one anticipated that we would face an unprecedented pandemic that would last a year or more. 2020 is unusual, to me, pandemic, new job, working, challenges, learning, vocabularies, and algorithms are key words of 2020. Time flies and everything will pass, we all hope that tomorrow will be better. For the summary of t...

Read more

详解 KCP 协议的原理和实现

1. 引言 KCP 是一个快速可靠的 ARQ (Automatic Repeat-reQuest, 自动重传请求) 协议, 采用了不同于 TCP 的自动重传策略, 有着比 TCP 更低的网络延迟. 实际通常使用 KCP over UDP 代替 TCP, 应用在网络游戏和音视频传输中. KCP 的实现短小精悍, 非常适合学习. KCP 的 ARQ 机制与 TCP 类似, 只是部分策略不同, 学习 KCP 也有助于我们理解 TCP. 本文讨论 KCP 的原理和实现, 包括它的 ARQ 机制, 拥塞控制等. 笔者并不想直接贴出大段代码然后逐行分析, 因此本文各节会先用图文介绍 KCP 的各个机制, 然后再展示代码并分析它的实现. KCP 源码的可读性还是比较好的, 建议大家阅读本文的同时...

Read more

Subsocks: 用 Go 实现一个 Socks5 安全代理

笔者最近读完了 The Go Programming Language, 想写点东西练练手. Go 比较适合写服务器软件, 之前又学习了下 Socks5 协议, 于是决定写一个 Socks5 代理服务器. 目前基本功能已经完成, 部分思路参考了 ginuerzh/gost. 我给它起名为 Subsocks, sub- 意为在 … 之下 (类似于 "subway"). 项目 Repository 在这里: luyuhuang/subsocks. 这里做一个介绍并简单总结下它的实现. 使用 一个 Subsocks 进程可以是客户端或服务端, 这取决于配置. 客户端会接收来自应用 (如浏览器) 的 Socks5 请求, 然后将其封装在指定的安全协议 (如 HTTPS) 中, 然后发送给服...

Read more

Printing parameters in Lua traceback

When an error occurs, Lua will print a traceback of the call stack, it helps us to find bugs. In many cases, however, a call stack traceback is not enough for us to find out the problem. We need more information, such as the environment, parameters of each function call, even all local variables of the stack. I decide to modify Lua to improve t...

Read more

Lua 夏令时时区问题

我之前的一篇文章介绍了怎样在服务器和客户端之间同步时间和时区. 同步时间相对简单些, 本质就是一个时间差; 而时区相对复杂些. 那篇文章介绍的方法有一个问题: 在客户端的时区启用了夏令时的时候, 客户端得到的本地时间会比实际快一个小时. 原因是求客户端时区的方法不对. 例如, 太平洋时区本为 UTC-0800, 而当客户端处于太平洋时区的 2020 年 10 月 29 日, 此时太平洋时区启用夏令时, 时区应为 UTC-0700. 如果使用这样的方法 local now = os_time() local CLIENT_TIMEZONE = math.floor(os.difftime(now, os_time(os_date("!*t", now)))) 求得的时区 CLIEN...

Read more

Lua next 函数的一个有趣问题

熟悉 Lua 的同学都知道, Lua 是允许在 for ... pairs 循环中修改和删除表中元素的. 下面这样的代码是没有任何问题的: local t = {a = 1, b = 2, c = 3} for k, v in pairs(t) do if v == 1 then t[k] = nil end end 但是, 如果我们在遍历时既删除元素又新增元素, 就会有问题了. 比如说: local t = {a = 1, b = 2, c = 3} for k, v in pairs(t) do if v == 1 then t[k] = nil t[k .. 1] = v + 1 end en...

Read more

A simple way to turn callback pattern to coroutine pattern in Lua

My game project is written by Lua. However, its framework does not provide a coroutine pattern, it uses a simple callback pattern instead. For example, to send an http request and receive the response, you must write like this: http_get("https://luyuhuang.tech/sitemap.xml", function(code, content) if code ~= 200 then print("an error...

Read more

全排列问题

给定 n 个不同的元素, 问有多少种不同的排列方式. 这就是全排列问题. 我们高中时就学过排列公式 $A_n^m = \frac{n!}{(n-m)!}$, 因此对于 n 个元素, 全排列数等于 $A_n^n = \frac{n!}{(n-n)!} = n!$ . 例如对于序列 [1, 2, 3] 全排列为 [1, 2, 3] [1, 3, 2] [2, 1, 3] [2, 3, 1] [3, 1, 2] [3, 2, 1] 共 $3! = 6$ 种. 这里我们讨论 Leetcode 上的三道全排列问题. 1. 全排列 题目源自 Leetcode 46 题 给定一个没有重复数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3] 输出: [ ...

Read more