日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

终于写完轮子一部分:tcp代理 了,记录一下

發(fā)布時間:2025/3/8 编程问答 27 如意码农
生活随笔 收集整理的這篇文章主要介紹了 终于写完轮子一部分:tcp代理 了,记录一下 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

24年終自己立了flag: 25年做些輪子玩(用于浪費生命,賺不了錢)

所以25年就準備用c#寫一個網(wǎng)絡代理NZOrz(nginx知道吧,就那玩意兒干的事),包含 udp/tcp/http1 2 3,

至于為啥不用rust寫,主要由于某臺電腦某些不可告知的原因不方便安裝rust,所以等我寫完c#的,后面有空再說吧(應該25年沒時間了吧)

代碼借鑒出處

秉承將生命浪費到底的造輪子精神,實力不行就盡可能借鑒(抄襲,讀書人的事,怎么能說呢)

所以這里首先列舉一下借鑒出處

  1. 借鑒 Kestrel 的 socket 處理核心 (理論上基于Kestrel也是可行的)
  2. 借鑒 Yarp 各項代理處理 (實現(xiàn)只有http)

所以整體實現(xiàn)上都是socket 上層做多線程處理,不編寫與系統(tǒng)內(nèi)核交互或者其他io事件庫打交道的代碼

(為啥?要打跨平臺交道,我不如直接用 rust 寫 linux的,window寫不寫看心情,反正服務器是王道是不是)

局限

不得不先提一個局限,dotnet 的socket 沒有提供統(tǒng)一的跨進程socket轉移api,因為dotnet是跨平臺的,不同系統(tǒng)存在差異,該issue Migrate Socket between processes 已經(jīng)多年沒有下文了

所以不好做到熱重啟

初步完成進度

  • TCP server core
  • TCP proxy core
  • dns (use system dns, no query from dns server )
  • LoadBalancingPolicy
  • Passive HealthCheck
  • TCP Connected Active HealthCheck
  • Configuration
  • reload config and rebind
  • Log
  • UDP server core
  • Config Validators
  • UDP proxy core
  • HTTP1 server core
  • HTTP2 server core
  • HTTP3 server core
  • HTTP proxy core
  • Metrics

對,目前主要是完成了基礎的 tcp 部分(代理協(xié)議不支持,畢竟有那么多,時間也有限),下一步以 udp 為優(yōu)先,(文檔嗎?等我先完成再說)

tcp代理使用

目前沒有提供現(xiàn)成打包好的exe或者docker鏡像,畢竟離完成還有很遠的距離

要玩可以這樣

建一個 net8.0 或者net9.0 的Console 項目

安裝package

dotnet add package NZ.Orz --version 0.0.0.2-beta

入口代碼

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NZ.Orz;
using NZ.Orz.ReverseProxy.L4; var app = NZApp.CreateBuilder(args)
.UseJsonConfig()
.Build(); await app.RunAsync();

配置 文件 appsettings.json

{
"Logging": {
"LogLevel": {
"Default": "Information"
}
},
"ReverseProxy": {
"Routes": {
"apidemo": {
"Protocols": "TCP",
"Match": {
"Hosts": [ "*:5000" ]
},
"ClusterId": "apidemo",
"RetryCount": 1,
"Timeout": "00:00:11"
}
},
"Clusters": {
"apidemo": {
"LoadBalancingPolicy": "RoundRobin",
"HealthCheck": {
"Active": {
"Enable": false,
"Policy": "Connect"
}
},
"Destinations": [
{
"Address": "[::1]:5144"
},
{
"Address": "[::1]:5146"
},
{
"Address": "google.com:998"
},
{
"Address": "www.baidu.com"
},
{
"Address": "http://google.com"
},
{
"Address": "https://google.com"
}
]
}
}
}
}

然后啟動就行, 啟動log大致如下

info: NZ.Orz.Server.ReverseProxy[18]
Config changed. Starting the following endpoints: [Protocols: TCP,Route: apidemo,EndPoint: 0.0.0.0:5000],[Protocols: TCP,Route: apidemo,EndPoint: [::]:5000]
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: D:\code\edge\l4proxy\src\L4Proxy\bin\Debug\net8.0

當然,運行中 如果改動appsettings.json內(nèi)容,會根據(jù)配置 重新監(jiān)聽變動端口/重建路由表等等

也算是一定程度彌補無法熱重啟的問題

改動tcp的數(shù)據(jù)

如果想改動tcp的數(shù)據(jù),可以實現(xiàn)中間件 ITcpMiddleware

比如

public class EchoMiddleware : ITcpMiddleware
{
public int Order => 0; public Task<ReadOnlyMemory<byte>> OnRequest(ConnectionContext connection, ReadOnlyMemory<byte> source, CancellationToken cancellationToken, TcpConnectionDelegate next)
{
Console.WriteLine($"{DateTime.Now} {connection.LocalEndPoint.ToString()} request size: {source.Length}");
return Task.FromResult(source);
} public Task<ReadOnlyMemory<byte>> OnResponse(ConnectionContext connection, ReadOnlyMemory<byte> source, CancellationToken cancellationToken, TcpConnectionDelegate next)
{
Console.WriteLine($"{DateTime.Now} {connection.SelectedDestination.EndPoint.ToString()} reponse size: {source.Length}");
//source = Encoding.UTF8.GetBytes("HTTP/1.1 400 Bad Request\r\nDate: Sun, 18 Oct 2012 10:36:20 GMT\r\nServer: Apache/2.2.14 (Win32)\r\nContent-Length: 0\r\nContent-Type: text/html; charset=iso-8859-1\r\nConnection: Closed\r\n\r\n").AsMemory();
//connection.Abort();
return Task.FromResult(source);
}
}

然后注入ioc就行

var app = NZApp.CreateBuilder(args)
.ConfigServices(services =>
{
services.AddSingleton<ITcpMiddleware, EchoMiddleware>();
})
.UseJsonConfig()
.Build();

配置簡單說明

詳細等以后寫文檔再說吧

Protocols 支持 TCP

Hosts 支持后綴匹配, 比如匹配所有實例5000端口就可以寫 *:5000, 匹配某個實例如 192.1.1.1,3000端口就可以寫 192.1.1.1:3000

(路由表實現(xiàn)采用 前綴樹+字典+SIEVE cahce)

服務發(fā)現(xiàn)目前只支持 DNS, 但不支持指定 dns server, 因為 dns不支持,以后再說吧

HealthCheck 支持主動 被動 二選一,不支持一起用, 主動 暫時只支持 socket connect 成功檢查

LoadBalancingPolicy 支持四種 Random , RoundRobin , LeastRequests , PowerOfTwoChoices

先就這樣,其他等我慢慢實現(xiàn)

大家有空的話,能否在 GitHub https://github.com/fs7744/NZOrz 點個 star 呢?畢竟借鑒代碼也不易呀 哈哈哈哈哈

總結

以上是生活随笔為你收集整理的终于写完轮子一部分:tcp代理 了,记录一下的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。