C#是一种流行的编程语言,而MessagePack是一种二进制序列化格式,用于在网络上高效传递数据。在C#中使用MessagePack可以通过安装和使用MessagePack NuGet包来实现。以下是使用MessagePack的示例代码:

首先,安装MessagePack NuGet包。可以使用Visual Studio中的NuGet包管理器来安装它,或在命令行中使用以下命令安装它:

Install-Package MessagePack

然后,在代码中使用MessagePack进行序列化和反序列化。以下是一个使用MessagePack进行序列化和反序列化的示例:

using System;
using MessagePack;

[MessagePackObject]
public class Person
{
    [Key(0)]
    public string Name { get; set; }

    [Key(1)]
    public int Age { get; set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 使用MessagePack序列化对象
        var person = new Person("Tom", 20);
        var bytes = MessagePackSerializer.Serialize(person);

        // 使用MessagePack反序列化对象
        var deserializedPerson = MessagePackSerializer.Deserialize<Person>(bytes);

        Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");
    }
}

在上面的示例中,定义了一个Person类,它包含了NameAge两个属性,并使用MessagePackObjectKey属性来标记需要进行序列化和反序列化的属性。

Main方法中,创建了一个Person对象,并使用MessagePackSerializer.Serialize方法将其序列化为二进制数据,然后使用MessagePackSerializer.Deserialize方法将二进制数据反序列化为Person对象。最后输出了反序列化后的Person对象的属性。

需要注意的是,使用MessagePack进行序列化和反序列化时,需要保证序列化和反序列化的类型是一致的。否则可能会出现异常。

本文将指导使用 xcaddy 自定义编译 Caddy。

PS:本文同时适用于 Debian 10 Buster 以及 Ubuntu 20.04 Focal

xcaddy 是 Caddy 官方制作的用于自定义编译 Caddy 的工具,它可以帮助我们快速的编译出符合自己需求的 Caddy。

安装 xcaddy

我们按照官方的安装方法,首先,安装一些必要的软件包:

apt update
apt upgrade -y
apt install curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates

然后按照官方教程安装 Go:

wget https://go.dev/dl/go1.19.5.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.19.5.linux-amd64.tar.gz

然后把 go 加入系统环境变量:

echo "export PATH=\$PATH:/usr/local/go/bin" >> /etc/profile

然后加入 Caddy 的 GPG 公钥和 apt 源:

curl -sSL https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key | gpg --dearmor > /usr/share/keyrings/xcaddy.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/xcaddy.gpg] https://dl.cloudsmith.io/public/caddy/xcaddy/deb/debian any-version main" > /etc/apt/sources.list.d/xcaddy.list

然后更新系统后即可安装 xcaddy:

apt update
apt install xcaddy

重启打开 SSH 后检查一下 go 和 xcaddy 的版本:

root@debian ~ # go version
go version go1.19.5 linux/amd64

root@debian ~ # xcaddy version
v0.3.1 h1:XKmnGnGTeB53hLUgnGr/R4JbTNSxh8IBAFcJkrtycso=

自定义编译 Caddy

我们可以选择一些自己喜欢的模块,比如缓存模块和 Brotli 压缩模块:

xcaddy build \
    --with github.com/caddyserver/cache-handler \
	--with github.com/ueffel/caddy-brotli

经过一段时间的编译以后,我们就可以在当前目录下看到一个名为 caddy 的二进制文件,这就是我们自定义编译的 Caddy 了。

自定义 Caddy 和系统 Caddy 共存

如果我们想要自定义 Caddy 和系统 Caddy 共存,可以使用官方的教程

首先,按照我们的教程安装 Caddy,安装完毕后,先停止 Caddy 服务:

systemctl stop caddy

然后使用 dpkg-divert 命令将系统 Caddy 的二进制文件移动到 /usr/bin/caddy.default 并做软链接:

dpkg-divert --divert /usr/bin/caddy.default --rename /usr/bin/caddy

然后把我们自己编译好的 Caddy 二进制文件移动到 /usr/bin/caddy.custom

mv ./caddy /usr/bin/caddy.custom

然后设置优先级,让我们的自定义 Caddy 优先启动:

update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.default 10
update-alternatives --install /usr/bin/caddy caddy /usr/bin/caddy.custom 50

此时我们可以看到默认的 /usr/bin/caddy 已经是我们自定义的 Caddy 了:

root@debian ~ # ls -l /usr/bin/caddy
lrwxrwxrwx 1 root root 23 Jan 22 10:52 /usr/bin/caddy -> /etc/alternatives/caddy*

root@debian ~ # ls -l /etc/alternatives/caddy
lrwxrwxrwx 1 root root 21 Jan 22 10:52 /etc/alternatives/caddy -> /usr/bin/caddy.custom

我们也可以使用 update-alternatives --config caddy 命令来切换系统安装的 Caddy 和自定义的 Caddy:

root@be ~ # update-alternatives --config caddy
There are 2 choices for the alternative caddy (providing /usr/bin/caddy).

  Selection    Path                    Priority   Status
------------------------------------------------------------
* 0            /usr/bin/caddy.custom    50        auto mode
  1            /usr/bin/caddy.custom    50        manual mode
  2            /usr/bin/caddy.default   10        manual mode

Press <enter> to keep the current choice[*], or type selection number:

我们可以看到默认的 Caddy 二进制文件是我们自定义的,你可以输入 0(按照优先级自动) 1(手工切换自定义 Caddy) 或 2(使用系统默认 Caddy)来修改并切换默认的 Caddy 版本。

要将 Rocky Linux 更换为国内源,您可以按照以下步骤进行操作:

1. 备份当前源文件

在更改之前,最好备份一下当前的源文件,以防万一。可以使用以下命令将当前的源文件备份到 /etc/yum.repos.d/ 目录中:

sudo cp /etc/yum.repos.d/Rocky-*.repo /etc/yum.repos.d/Rocky-*.repo.backup

2. 下载新的源文件

您可以使用以下命令下载中国科技大学(USTC)的 Rocky Linux 源文件,并将其放置在 /etc/yum.repos.d/ 目录中:

sudo curl -o /etc/yum.repos.d/Rocky-BaseOS.repo http://mirrors.ustc.edu.cn/rocky/8/BaseOS/x86_64/os/Rocky-BaseOS.repo
sudo curl -o /etc/yum.repos.d/Rocky-AppStream.repo http://mirrors.ustc.edu.cn/rocky/8/AppStream/x86_64/os/Rocky-AppStream.repo

3. 清除缓存并更新

完成更改后,可以使用以下命令清除缓存,并使用新的源更新软件包:

sudo yum clean all
sudo yum update

完成这些步骤后,Rocky Linux 环境就成功更换为国内源了。

要更换Ubuntu 22的国内源,可以按照以下步骤操作:

1.打开终端,进入 /etc/apt/ 目录

cd /etc/apt/

2.备份原有的 sources.list 文件

sudo cp sources.list sources.list.backup

3.编辑 sources.list 文件

sudo nano sources.list

4.将文件内容替换为以下内容,这是清华大学镜像源的例子,可以根据自己的需要来修改

# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute-security main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute-proposed main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ hirsute-proposed main restricted universe multiverse

5.保存并退出编辑器,运行以下命令更新软件包列表

sudo apt update

这样,Ubuntu 22 就已经成功更换了国内源。

Nginx 可以采用以下几种方式来防止被 CC(DDoS 攻击):

1. 限制连接速率:可以通过 ngx_http_limit_conn_module 和 ngx_http_limit_req_module 模块限制每个 IP 的连接速率和请求速率,以确保服务器的连接和请求资源分配公平。

2. 过滤恶意请求:可以通过 ngx_http_access_module 模块进行黑白名单控制,阻止恶意请求来自黑名单 IP,减轻服务器的压力。在此基础上可以使用 ngx_http_referer_module 模块进行防盗链。

3. 控制请求大小:可以使用 ngx_http_request_limit_zone_module 和 ngx_http_client_body_module 模块来限制请求大小,防止非法的大量数据提交。

4. 开启缓存:建立服务器缓存来避免过多的请求将达到后端服务器,可以使用 ngx_http_proxy_module 和 ngx_http_fastcgi_module 模块来提高网站的访问速度,同时缓存能够帮助减轻服务器压力并防止被 CC 攻击。

5. 配置 Keep-Alive:启动 keep-alive 功能可以让浏览器和服务器之间的TCP连接保持长连接,有效减轻服务器压力同时提高访问速度。可以使用 ngx_http_headers_module 模块来配置 keep-alive 功能。

6. 使用专业的防火墙及负载均衡:在高访问量的情况下,使用专业的防火墙及负载均衡设备,将请求分配到不同服务器上,提高服务器性能,同时可以在防火墙上进行过滤非法IP,增强安全性。

这些方法可以有效地增强 Nginx 的安全性,更好地防止 CC(DDoS 攻击)和其他安全问题。

HTML 代码:

<!DOCTYPE html>
<html>
<head>
 <title>JavaScript 画板</title>
 <style>
  canvas {
   border: 1px solid black;
  }
 </style>
</head>
<body>
 <div>
  <canvas id="myCanvas" width="500" height="500"></canvas>
 </div>
 <div>
  <button onclick="setColor('red')">红色</button>
  <button onclick="setColor('green')">绿色</button>
  <button onclick="setColor('blue')">蓝色</button>
  <button onclick="setColor('black')">黑色</button>
  <button onclick="clearCanvas()">清除画布</button>
 </div>
 <script src="paint.js"></script>
</body>
</html>

在 HTML 中,我们创建了一个 canvas 元素和一些按钮用于设置画笔颜色和清空画布。canvas 元素用于绘制图像。

JavaScript 代码(保存在 paint.js 文件中):

var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var color = "black";
var painting = false;

function setColor(newColor) {
 color = newColor;
}

function startPainting() {
 painting = true;
}

function stopPainting() {
 painting = false;
}

function draw(event) {
 if (!painting) {
  return;
 }

 context.beginPath();
 context.arc(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop, 10, 0, Math.PI * 2);
 context.fillStyle = color;
 context.fill();
 context.closePath();
}

function clearCanvas() {
 context.clearRect(0, 0, canvas.width, canvas.height);
}

canvas.addEventListener("mousedown", startPainting);
canvas.addEventListener("mouseup", stopPainting);
canvas.addEventListener("mousemove", draw);

在 JavaScript 中,我们获取了 canvas 元素和用于绘制的上下文。我们还定义了一些变量,用于存储当前画笔颜色以及当前是否正在绘制。

setColor 函数用于设置画笔颜色,它会在点击颜色按钮时调用。startPainting 和 stopPainting 函数用于开启和关闭绘制,它们会在鼠标按下和松开时调用。draw 函数用于实际的绘制操作,它会在鼠标移动时调用。clearCanvas 函数用于清空画布,它会在点击清除画布按钮时调用。

最后,我们为 canvas 元素的 mousedown、mouseup 和 mousemove 事件添加了监听器,用于开始绘制、停止绘制和实际绘制的操作。

SQL Server 2019 支持正则表达式,您可以使用LIKE运算符与正则表达式元字符结合使用来匹配模式。

以下是一个示例,用于使用正则表达式从表中选择具有特定字符模式的行:

假设您有一个名为employees的表,其中包含full_name列。您可以使用以下查询来选择full_name列中以字母“a”开头,并以字母“y”结尾的所有行:

SELECT full_name
FROM employees
WHERE full_name LIKE 'a%y';

在上面的查询中,%是一个SQL通配符,代表零个或多个任意字符。因此,查询选择了full_name列中以字母“a”开头,并以字母“y”结尾的所有行。 此查询仅匹配以字母“a”开头,并以字母“y”结尾的字符串,而不是包含任意位置的字母“a”和“y”的字符串。

如果要使用更复杂的模式,可以将通配符与正则表达式结合使用。例如,要选择所有包含至少一个数字的full_name,您可以执行以下查询:

SELECT full_name
FROM employees
WHERE full_name LIKE '%[0-9]%';

在上面的查询中,[0-9]是一个正则表达式字符集,代表任何数字字符。因此,查询选择了full_name列中包含至少一个数字的所有行。

请注意,正则表达式功能在不同数据库管理系统和版本之间可能会有所不同。如果您使用的是不同的版本或数据库,建议您查看相关文档以了解它们支持的SQL语言和函数。

在 SQL Server 中,可以使用 JSON_VALUE 函数查询 JSON 数据的特定值,使用 JSON_QUERY 函数查询 JSON 数据的特定对象,使用 JSON_MODIFY 函数更新 JSON 数据。

以下是一些示例:

1. 查询特定 JSON 字段的值:

SELECT JSON_VALUE(json_column, '$.field_name')
FROM table_name;

2. 查询 JSON 对象并返回整个 JSON 字符串:

SELECT JSON_QUERY(json_column)
FROM table_name;

3. 查询 JSON 对象中的特定字段:

SELECT JSON_QUERY(json_column, '$.field_name')
FROM table_name;

4. 在 JSON 对象中更新现有值:

UPDATE table_name
SET json_column = JSON_MODIFY(json_column, '$.field_name', 'new_value')
WHERE some_condition;

C# 中使用正则表达式替换字符串可以使用 Regex 类的 Replace 方法。方法定义如下:

public static string Replace(string input, string pattern, string replacement);

其中,input 表示要进行替换的字符串,pattern 表示要匹配的正则表达式模式,replacement 表示要替换成的字符串。

例如,假设要把一个字符串中所有的数字替换为”#”,可以使用以下代码:

string input = "1234567890";
string pattern = @"d";
string replacement = "#";
string result = Regex.Replace(input, pattern, replacement);

其中,正则表达式模式 @”d” 表示匹配任意一个数字字符。执行完以上代码后,result 的值应该是”##########”。

为了深度克隆PooledList<T>,你需要将原始列表中的元素逐个复制到新列表中。由于是“深度”克隆,所以必须创建后生成的新列表包含与原始列表相同类型的新对象,而不是原始列表中对象的引用。

以下是一个示例方法,可用于深度克隆PooledList<T>

public static PooledList<T> Clone<T>(PooledList<T> original) where T : class, new()
{
    var newList = new PooledList<T>();
    for (int i = 0; i < original.Count; i++)
    {
        T originalItem = original[i];
        T newItem = new T();
        //然后将原始项目中的值复制到新项目中
        //在此之前,请确保T类型具有可复制的属性或字段
        newList.Add(newItem);
    }
    return newList;
}

请注意,为了深度克隆PooledList<T>,T类型必须满足以下条件:

1. 它必须是引用类型(即类或接口);
2. 它必须具有默认构造函数(即无参构造函数);
3. 它的字段或属性必须是可复制的。

如果上述条件不被满足,那么需要使用自定义方法来处理T类型的深度复制过程。