پرش به مطلب اصلی

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"
}

تنظیمات

گزینهپیش‌فرضتوضیح
fecfalseفعال‌سازی Reed-Solomon FEC برای packetهای KCP
fec-data-shards10تعداد data shardهای هر block
fec-parity-shards3تعداد 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معنی
0x00data
0xF0ping
0xFFclose

data frameها بعد از بایت flag، payload واقعی stream را دارند.

تنظیمات KCP فعلی

این تنظیمات از JSON قابل تغییر نیستند:

گزینه KCPمقدار
nodelay1
interval10 ms
resend2
flowctl0
send window2048
receive window2048
ping interval3000 ms
no-receive timeout6000 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 بدهد، TcpOverUdpServer close 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 را بالا ببرد و مشکل اصلی مسیر را حل نکند.