TcpOverUdpServer
TcpOverUdpServer سمت سرور TcpOverUdpClient است. این نود datagramهای KCP را از سمت قبلی میگیرد، stream اصلی را بازسازی میکند و payload را مثل یک stream معمولی به نود بعدی میدهد. پاسخهای سمت بعدی دوباره داخل KCP packet میشوند و به سمت قبلی برمیگردند.
جایگاه رایج
UdpListener -> TcpOverUdpServer -> TcpConnector
UdpListener -> TcpOverUdpServer -> MuxServer -> TcpConnector
سمت مقابل:
TcpListener -> TcpOverUdpClient -> UdpConnector
نمونه تنظیم بدون FEC
{
"name": "tcp-over-udp-server",
"type": "TcpOverUdpServer",
"settings": {},
"next": "service-stream-node"
}
نمونه تنظیم با FEC
{
"name": "tcp-over-udp-server",
"type": "TcpOverUdpServer",
"settings": {
"fec": true,
"fec-data-shards": 10,
"fec-parity-shards": 3
},
"next": "service-stream-node"
}
تنظیمات
| گزینه | پیشفرض | توضیح |
|---|---|---|
fec | false | فعالسازی Reed-Solomon FEC برای packetهای KCP |
fec-data-shards | 10 | تعداد data shardهای هر block |
fec-parity-shards | 3 | تعداد parity shardهای هر block |
تنظیمات FEC باید دقیقا با سمت TcpOverUdpClient یکی باشد. اگر یک سمت FEC روشن و سمت دیگر خام باشد، یا shardها فرق کنند، traffic قابل decode نخواهد بود.
رفتار FEC در سمت server
وقتی fec فعال است، TcpOverUdpServer packetهای قبلی را FEC-wrapped در نظر میگیرد:
- data shardهای سالم را بلافاصله وارد KCP میکند.
- parity shardها را برای بازسازی datagramهای گمشده استفاده میکند.
- packetهای FEC نامعتبر را محافظهکارانه drop میکند.
- در مسیر برگشت هم datagramهای KCP را با همان قالب FEC میفرستد و بعد از هر block، parity تولید میکند.
اگر FEC خاموش باشد، مسیر همان KCP-only قدیمی است و هیچ framing اضافه FEC وجود ندارد.
مدل KCP
وقتی line init میشود، TcpOverUdpServer session KCP میسازد، timer loop را شروع میکند و یک ping داخلی queue میکند. packetهای ورودی از سمت UDP وارد KCP میشوند. بعد از آماده شدن stream، payloadها با توجه به flag داخلی پردازش میشوند.
flagهای داخلی
| flag | معنی |
|---|---|
0x00 | data |
0xF0 | ping |
0xFF | close |
data frameها بعد از بایت flag، payload واقعی stream را دارند.
تنظیمات KCP فعلی
این تنظیمات از JSON قابل تغییر نیستند:
| گزینه KCP | مقدار |
|---|---|
nodelay | 1 |
interval | 10 ms |
resend | 2 |
flowctl | 0 |
| send window | 2048 |
| receive window | 2048 |
| ping interval | 3000 ms |
| no-receive timeout | 6000 ms |
MTU از GLOBAL_MTU_SIZE گرفته میشود و وقتی FEC روشن باشد overhead FEC از بودجه packet کم میشود.
جریان داده
- مسیر packet به stream:
UdpListenerیا نود packet-preserving قبلی، datagramها را بهTcpOverUdpServerمیدهد. نود آنها را وارد KCP میکند و stream بازسازیشده را بهnextمیدهد. - مسیر stream به packet: payload از
nextبه KCP داده میشود، به datagram تبدیل میشود و به سمت previous برمیگردد.
close، timeout و backpressure
- اگر close frame از peer برسد، state پاک میشود و هر دو جهت finish میشوند.
- اگر نود بعدی finish بدهد،
TcpOverUdpServerclose frame را از طریق KCP میفرستد، flush میکند و سمت قبلی را finish میکند. - بعد از حدود
3000 msبدون receive activity، ping داخلی ارسال میشود. - بعد از حدود
6000 msبدون receive activity، line بسته میشود. - اگر queue ارسال KCP زیاد شود، نود بعدی pause میشود و بعد از پایین آمدن queue resume میگیرد.
نکتههای عملی
- این نود بدون
TcpOverUdpClientسمت مقابل کاربرد ندارد. - previous side باید datagram boundary را حفظ کند.
- اگر loss مسیر متوسط است،
fec=trueبا مقدار پیشفرض10/3نقطه شروع خوبی است. - اگر bandwidth محدود است و loss کم دارید، FEC را خاموش یا parity را کمتر انتخاب کنید.
- اگر loss خیلی شدید است، FEC ممکن است فقط مصرف bandwidth را بالا ببرد و مشکل اصلی مسیر را حل نکند.