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

TcpListener

TcpListener نود سرور TCP است. روی یک آدرس و پورت یا بازه پورت گوش می‌دهد، برای هر client پذیرفته‌شده یک line جدید می‌سازد و آن line را به نود بعدی زنجیر تحویل می‌دهد.

این نود معمولا ابتدای زنجیر قرار می‌گیرد:

TcpListener -> ... -> TcpConnector

نمونه تنظیم

{
"name": "inbound-listener",
"type": "TcpListener",
"settings": {
"address": "0.0.0.0",
"port": 443,
"nodelay": true,
"interface": "eth0",
"fwmark": 10,
"balance-group": "public-443",
"balance-interval": 30000,
"multiport-backend": "socket",
"whitelist": [
"192.168.1.0/24",
"2001:db8::/64"
]
},
"next": "next-node-name"
}

فیلدهای ضروری

فیلدتوضیح
nameنام دلخواه نود
typeباید دقیقا TcpListener باشد
nextنودی که lineهای پذیرفته‌شده را دریافت می‌کند
settings.addressآدرس bind، مثل 0.0.0.0، :: یا IP مشخص
settings.portیک عدد مثل 443 یا آرایه دو عضوی مثل [40000, 40100]

در JSON واقعی این دو کلید داخل settings با نام‌های address و port نوشته می‌شوند.

نسخه فعلی port را به شکل string مثل "40000-40100" parse نمی‌کند؛ برای بازه حتما از آرایه دو عضوی استفاده کنید.

تنظیمات اختیاری

گزینهپیش‌فرضتوضیح
nodelayfalseفعال‌سازی TCP_NODELAY روی socketهای پذیرفته‌شده
interface-محدود کردن listener به interface محلی. در Linux از SO_BINDTODEVICE استفاده می‌شود.
fwmark-socket mark در سیستم‌هایی که SO_MARK دارند
balance-group-قرار دادن چند listener هم‌پورت در یک گروه توزیع
balance-interval-مدت sticky بودن client در گروه balance، به میلی‌ثانیه
multiport-backendوابسته به runtimeبرای بازه پورت: iptables یا socket
whitelist-لیست IP یا CIDR مجاز، IPv4 و IPv6
هشدار

در نسخه فعلی سورس، TcpListener فیلد whitelist را parse می‌کند، اما blacklist را از JSON نمی‌خواند. اگر در configهای قدیمی blacklist دیده‌اید، برای نسخه فعلی روی آن حساب نکنید.

رفتار اتصال

وقتی client وصل می‌شود، TcpListener:

  • socket را روی worker مناسب قرار می‌دهد.
  • یک line جدید می‌سازد.
  • routing context را از اتصال پذیرفته‌شده پر می‌کند.
  • به نود بعدی upstream init می‌فرستد.
  • خواندن از socket client را شروع می‌کند.

مسیر داده:

  • client به زنجیر: خواندن از socket و ارسال upstream payload به next
  • زنجیر به client: دریافت downstream payload و نوشتن روی socket

backpressure و صف نوشتن

اگر client کند باشد و write کامل نشود، bufferها صف می‌شوند. وقتی صف از حدود 1 KB بزرگ‌تر شود نود بعدی pause می‌شود و وقتی socket دوباره writable شد resume می‌گیرد. اگر صف از حدود 16 MB عبور کند اتصال بسته می‌شود تا حافظه بی‌نهایت مصرف نشود.

timeout و balance

هر اتصال پذیرفته‌شده در جدول idle نگه داشته می‌شود. اتصال تازه ابتدا timeout کوتاه حدود 5s دارد و بعد از فعالیت، حدود 300s refresh می‌شود.

اگر چند TcpListener با balance-group و port مشترک داشته باشید، socket manager براساس IP client یک listener انتخاب می‌کند و تا پایان balance-interval همان client را sticky نگه می‌دارد.

whitelist

"whitelist": [
"10.0.0.0/8",
"192.168.1.20/32",
"2001:db8::/64"
]

اگر whitelist وجود داشته باشد، فقط clientهایی که match می‌شوند توسط این listener پذیرفته می‌شوند. اگر چند listener روی یک پورت دارید، ممکن است listener دیگری با filter متفاوت همان اتصال را بگیرد.

انتخاب multiport backend

  • socket: برای هر پورت یک socket جدا ساخته می‌شود. ساده‌تر و مستقل‌تر است.
  • iptables: برای بازه‌های بزرگ می‌تواند منابع کمتری مصرف کند، اما به محیط و ruleهای سیستم وابسته است.

برای بازه‌های کوچک، socket معمولا قابل فهم‌تر است. برای بازه‌های بزرگ، iptables می‌تواند کاربردی‌تر باشد، به شرطی که کنترل ruleهای سیستم را داشته باشید.