رفتن به محتوا
مبانی کامپیوتر و اینترنتاینترنت چطور کار می‌کنددرس ۹ از ۱۶

پورت، پروتکل و بسته‌ها

چند برنامه چطور از یک اتصال اینترنت استفاده می‌کنند: پورت به‌عنوان شماره‌ی واحد، پورت‌های معروف (22، 80، 443، 53، 5432)، پروتکل یعنی قرارداد، بسته و سرآیند، TCP و دست‌دادن سه‌مرحله‌ای، UDP، لایه‌های شبکه، و آزمایش واقعی با nc: گوش دادن، وصل شدن، Connection refused، فرق 127.0.0.1 و 0.0.0.0 و پورت‌های زیر 1024.

  • حدود ۲۵ دقیقه مطالعه
  • ۷ مثال اجراشده
  • ۳ تمرین با جواب
  • مقدماتی (از صفر مطلق)
  • به‌روزرسانی: ۲۹ مهر ۱۴۰۵

توی این درس یاد می‌گیری وقتی کامپیوترت فقط یک آدرس IP دارد، چطور مرورگر و تلگرام و برنامه‌ی موسیقی هم‌زمان از اینترنت استفاده می‌کنند و داده‌هایشان قاطی نمی‌شود. با پورت (شماره‌ی «واحد» داخل یک آدرس)، پروتکل (قرارداد حرف زدن)، بسته (تکه‌های کوچک داده) و دو پروتکل اصلی TCP و UDP آشنا می‌شوی. بعد با ابزار nc خودت یک «سرور» کوچک راه می‌اندازی، از ترمینال دیگری به آن وصل می‌شوی و خطای معروف Connection refused را با چشم خودت می‌سازی و می‌فهمی.

مسئله: یک آدرس، ده‌ها برنامه

Section titled “مسئله: یک آدرس، ده‌ها برنامه”

در درس قبل دیدی هر دستگاه یک آدرس IP دارد. ولی روی لپ‌تاپ تو هم‌زمان مرورگر با پنج تب، تلگرام، آپدیت ویندوز و یک بازی آنلاین به اینترنت وصل‌اند. داده‌ای که به IP تو می‌رسد، مال کدام‌شان است؟ روی سرور هم همین‌طور: یک سرور با یک IP هم‌زمان سایت، SSH و دیتابیس دارد. باید راهی باشد که داده‌ها در داخل کامپیوتر به برنامه‌ی درست برسند. این راه پورت است.

تشبیه: مجتمع اداری و شماره‌ی واحد

Section titled “تشبیه: مجتمع اداری و شماره‌ی واحد”

اگر IP آدرس یک ساختمان باشد، پورت شماره‌ی واحد داخل آن است. نامه‌رسان (شبکه) نامه را به ساختمان (IP) می‌رساند و نگهبان (سیستم‌عامل) با نگاه به شماره‌ی واحد (پورت) آن را به دفتر درست می‌دهد: واحد ۲۲ دفتر SSH، واحد ۸۰ دفتر وب، واحد ۵۴۳۲ دفتر دیتابیس. اگر نامه برای واحدی باشد که خالی است، نگهبان همان دم در پسش می‌فرستد: «اینجا کسی نیست» (همان Connection refused).

پروتکل هم زبان و آداب نامه‌نگاری هر دفتر است: دفتر وب فقط نامه‌هایی را می‌فهمد که به زبان HTTP نوشته شده باشند، دفتر SSH زبان خودش را دارد. پورت می‌گوید به کجا، پروتکل می‌گوید چطور.

پورت عددی بین ۰ تا ۶۵۵۳۵ است. چرا این عدد؟ درس بیت و بایت: پورت ۲ بایت (۱۶ بیت) است و 216 = ۶۵٬۵۳۶. یک اتصال با دو جفت «آدرس:پورت» شناخته می‌شود، مثلاً 192.168.1.20:51344 → 93.184.215.14:443: مرورگر تو از پورت ۵۱۳۴۴ با پورت ۴۴۳ سرور حرف می‌زند. سمت سرور پورت ثابت و معروف است (۴۴۳)، سمت تو یک پورت موقت که سیستم‌عامل برای هر اتصال انتخاب می‌کند؛ برای همین پنج تب مرورگر قاطی نمی‌شوند: هر کدام پورت موقت خودش را دارد.

پورت‌هایی که در این دوره‌ها مدام می‌بینی:

پورت پروتکل کار
22 SSH ورود امن به سرور (دوره‌ی لینوکس)
53 DNS تبدیل اسم به IP (درس DNS)
80 HTTP وب بدون رمزنگاری
443 HTTPS وب رمزنگاری‌شده
25 / 587 SMTP ارسال ایمیل
3306 MySQL دیتابیس
5432 PostgreSQL دیتابیس (دوره‌ی SQL)
8080، 8000، 3000 (قرارداد غیررسمی) برنامه‌های در حال توسعه

این فهرست در هر لینوکسی در فایل /etc/services هست:

Terminal window
grep -wE "^(ssh|domain|http|https|postgresql)" /etc/services
خروجی
ssh 22/tcp # SSH Remote Login Protocol
domain 53/tcp # Domain Name Server
domain 53/udp
http 80/tcp www # WorldWideWeb HTTP
https 443/tcp # http protocol over TLS/SSL
https 443/udp # HTTP/3
postgresql 5432/tcp postgres # PostgreSQL Database

(grep خط‌هایی را که با این اسم‌ها شروع می‌شوند پیدا می‌کند؛ در دوره‌ی لینوکس یاد می‌گیری.) کنار هر پورت tcp یا udp آمده: دو روش متفاوت فرستادن داده که پایین‌تر می‌بینی.

پورت‌های زیر ۱۰۲۴ «ممتاز»اند: در لینوکس فقط مدیر سیستم (root) می‌تواند برنامه‌ای را روی آن‌ها راه بیندازد (مثال ۶). این یک قانون امنیتی قدیمی است تا هر کاربری نتواند خودش را جای وب‌سرور اصلی جا بزند.

بسته‌ها: داده تکه‌تکه سفر می‌کند

Section titled “بسته‌ها: داده تکه‌تکه سفر می‌کند”

یک فایل ۱۰ مگابایتی یک‌جا در شبکه فرستاده نمی‌شود. به بسته‌ها (packet) حدوداً ۱۵۰۰ بایتی تقسیم می‌شود و هر بسته جداگانه سفر می‌کند. هر بسته مثل یک پاکت نامه است: بیرونش سرآیند (header) با آدرس‌ها و شماره‌ها، داخلش تکه‌ای از داده. سرآیندها لایه‌لایه‌اند و هر لایه کار خودش را می‌کند:

هر لایه سرآیند خودش را دور داده‌ی لایه‌ی بالایی می‌پیچد: برنامه HTTP می‌نویسد، TCP پورت‌ها را اضافه می‌کند، IP آدرس‌ها را، و کارت شبکه آن را روی کابل یا موج می‌فرستد.

قشنگی این طراحی: مرورگر نمی‌داند داده با Wi-Fi می‌رود یا کابل یا فیبر؛ روترهای اینترنت هم نمی‌دانند داخل بسته HTTP است یا بازی. هر کس فقط لایه‌ی خودش را می‌خواند. (در کتاب‌ها مدل ۷ لایه‌ای OSI را هم می‌بینی؛ همین چهار لایه، با چند تقسیم بیشتر.)

TCP UDP
اتصال قبل از ارسال، «دست می‌دهند» بدون مقدمه، فقط می‌فرستد
رسیدن تضمین‌شده؛ بسته‌ی گم‌شده دوباره فرستاده می‌شود تضمینی نیست
ترتیب بسته‌ها به ترتیب تحویل برنامه می‌شوند ممکن است جابه‌جا برسند
سرعت کمی کندتر (رفت‌وبرگشت تأیید) سریع، سربار کم
تشبیه تماس تلفنی: «الو؟ صدام میاد؟» کارت‌پستال: می‌اندازی در صندوق
کاربرد وب، SSH، ایمیل، دیتابیس DNS، تماس صوتی و تصویری، بازی، استریم زنده

چرا تماس تصویری UDP است؟ چون اگر یک تکه از تصویر نیم ثانیه پیش گم شده، دوباره فرستادنش فایده‌ای ندارد؛ لحظه گذشته. ولی در دانلود یک فایل یا یک صفحه‌ی وب، حتی یک بایت گم‌شده همه‌چیز را خراب می‌کند؛ پس TCP.

TCP قبل از ارسال داده یک دست‌دادن سه‌مرحله‌ای (three-way handshake) انجام می‌دهد:

دست‌دادن TCP: بعد از این سه پیام، هر دو طرف می‌دانند دیگری آماده است و داده‌ها شماره‌گذاری‌شده رد و بدل می‌شوند.

اگر روی آن پورت هیچ برنامه‌ای نباشد، سرور به SYN با یک RST (reset، «رد») جواب می‌دهد؛ همان Connection refused. اگر یک فایروال بسته را بی‌صدا دور بیندازد، هیچ جوابی نمی‌آید و کلاینت آن‌قدر منتظر می‌ماند تا timeout شود. این دو پیام خطا دو داستان کاملاً متفاوت‌اند (اشتباه رایج ۲).

ابزار این درس nc (netcat) است: «چاقوی سوئیسی شبکه» که می‌تواند روی یک پورت گوش بدهد (مثل سرور) یا به یک پورت وصل شود (مثل کلاینت) و هر چه تایپ کنی را بفرستد. روی Ubuntu نصب است. برای چند مثال دو ترمینال کنار هم باز کن (در WSL یک پنجره‌ی دیگر، در Multipass دوباره multipass shell).

مثال ۱: اولین سرور و کلاینت تو

Section titled “مثال ۱: اولین سرور و کلاینت تو”

در ترمینال ۱ یک «سرور» راه بینداز که روی پورت ۹۰۰۰ گوش بدهد:

Terminal window
nc -l 127.0.0.1 9000

-l یعنی listen (گوش بده). چیزی چاپ نمی‌شود و منتظر می‌ماند. در ترمینال ۲ وصل شو و یک پیام بفرست:

Terminal window
echo "سلام از ترمینال دوم" | nc -N 127.0.0.1 9000

در ترمینال ۱ پیام ظاهر می‌شود و nc تمام می‌شود:

خروجی (ترمینال ۱)
سلام از ترمینال دوم

همین الان یک اتصال TCP کامل ساختی: دست‌دادن، ارسال داده و بستن اتصال. echo متن را تولید می‌کند و | آن را به nc می‌دهد؛ -N یعنی بعد از تمام شدن متن، اتصال را ببند. همه‌ی برنامه‌های شبکه، از مرورگر تا دیتابیس، در اساس همین کار را می‌کنند؛ فقط پروتکلشان (شکل پیام‌ها) پیچیده‌تر است. (اگر بدون echo و -N وصل شوی، هر خطی که در ترمینال ۲ تایپ کنی، در ترمینال ۱ ظاهر می‌شود: یک «چت» خیلی ساده. با Ctrl+C تمامش کن.)

حالا به پورتی وصل شو که هیچ برنامه‌ای رویش گوش نمی‌دهد:

Terminal window
nc -zv 127.0.0.1 9001
echo "exit=$?"
خروجی
nc: connect to 127.0.0.1 port 9001 (tcp) failed: Connection refused
exit=1

-z یعنی «فقط ببین پورت باز است، داده نفرست» و -v یعنی پرحرف (verbose) باش. کامپیوتر (همین 127.0.0.1) روشن و در دسترس است، ولی روی پورت ۹۰۰۱ کسی نیست؛ سیستم‌عامل فوراً «رد» برگرداند. پس Connection refused یعنی شبکه سالم است؛ برنامه نیست (یا روی پورت یا آدرس دیگری است). exit=1 کد خروج است: صفر یعنی موفق، غیر صفر یعنی شکست (در درس «چطور یاد بگیری» دیدی).

دوباره در ترمینال ۱ گوش بده (nc -l 127.0.0.1 9000) و در ترمینال ۲:

Terminal window
nc -zv 127.0.0.1 9000
خروجی
Connection to 127.0.0.1 9000 port [tcp/*] succeeded!

succeeded یعنی دست‌دادن TCP کامل شد: کسی آنجا گوش می‌دهد. این اولین قدم تشخیص هر مشکل «وصل نمی‌شود» است: پورت باز است یا نه؟ (nc -zv سرور 22 برای SSH، nc -zv سرور 5432 برای دیتابیس.)

مثال ۴: دیدن پورت‌های باز کامپیوتر

Section titled “مثال ۴: دیدن پورت‌های باز کامپیوتر”

کدام برنامه‌ها الان روی کدام پورت‌ها گوش می‌دهند؟

Terminal window
ss -tln
نمونه
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:*
LISTEN 0 1 127.0.0.1:9000 0.0.0.0:*
LISTEN 0 4096 [::]:22 [::]:*

ss (socket statistics): -t فقط TCP، -l فقط آن‌هایی که گوش می‌دهند (LISTEN)، -n شماره‌ها را به‌جای اسم نشان بده. ستون مهم Local Address:Port است: 0.0.0.0:22 یعنی SSH روی همه‌ی آدرس‌ها گوش می‌دهد، 127.0.0.1:9000 همان nc توست که فقط روی localhost است، و 127.0.0.53:53 سرویس DNS داخلی Ubuntu (درس DNS). [::] همان 0.0.0.0 برای IPv6 است. فهرست روی سیستم تو فرق می‌کند. (با sudo ss -tlnp اسم برنامه هم در ستون Process می‌آید؛ در دوره‌ی لینوکس.)

مثال ۵: ‎127.0.0.1 یا 0.0.0.0؟ (همان مشکل سناریو)

Section titled “مثال ۵: ‎127.0.0.1 یا 0.0.0.0؟ (همان مشکل سناریو)”

یک برنامه وقتی گوش می‌دهد، باید بگوید روی کدام آدرس. این تصمیم تعیین می‌کند چه کسی می‌تواند به آن برسد. در ترمینال ۱:

Terminal window
nc -l 127.0.0.1 9000

حالا در ترمینال ۲ به همان پورت ولی با IP واقعی کامپیوتر (همان که ip -br addr در درس قبل نشان داد؛ ماشین آزمایشی این درس 192.0.2.2 داشت) وصل شو، طوری که انگار از یک کامپیوتر دیگر در شبکه آمده‌ای:

Terminal window
nc -zv 192.0.2.2 9000
خروجی
nc: connect to 192.0.2.2 port 9000 (tcp) failed: Connection refused

برنامه روشن است ولی فقط روی 127.0.0.1 گوش می‌دهد، پس فقط از داخل همین کامپیوتر قابل‌دسترسی است. ترمینال ۱ را با Ctrl+C ببند و این بار روی 0.0.0.0 (یعنی «همه‌ی آدرس‌های این کامپیوتر») گوش بده:

Terminal window
nc -l 0.0.0.0 9002
Terminal window
nc -zv 192.0.2.2 9002
خروجی
Connection to 192.0.2.2 9002 port [tcp/*] succeeded!

این دقیقاً مشکل سناریو بود: دیتابیس‌ها (PostgreSQL، MySQL، Redis) به‌طور پیش‌فرض برای امنیت فقط روی 127.0.0.1 گوش می‌دهند. امن است، چون از بیرون دیده نمی‌شوند؛ و اگر واقعاً لازم است از بیرون در دسترس باشند، باید هم تنظیم برنامه را عوض کنی و هم با فایروال محدودش کنی (دوره‌ی SQL و لینوکس).

⚡ بررسی سریع

ss -tln نشان می‌دهد دیتابیس روی 127.0.0.1:5432 گوش می‌دهد. برنامه‌ای روی یک سرور دیگر می‌خواهد وصل شود. چه می‌بیند؟

مثال ۶: پورت‌های زیر ۱۰۲۴

Section titled “مثال ۶: پورت‌های زیر ۱۰۲۴”
Terminal window
nc -l 80
echo "exit=$?"
خروجی
nc: Permission denied
exit=1

کاربر معمولی نمی‌تواند روی پورت ۸۰ گوش بدهد. وب‌سرورهای واقعی (مثل nginx که در دوره‌ی خودش می‌بینی) با یک ترفند کار می‌کنند: با دسترسی مدیر شروع می‌شوند، پورت ۸۰ را می‌گیرند و بعد دسترسی‌شان را به یک کاربر معمولی کم می‌کنند. برای همین برنامه‌های در حال توسعه روی پورت‌هایی مثل ۸۰۰۰ و ۸۰۸۰ اجرا می‌شوند.

مثال ۷: UDP، بدون دست‌دادن

Section titled “مثال ۷: UDP، بدون دست‌دادن”

در ترمینال ۱ یک گیرنده‌ی UDP راه بینداز (-u یعنی UDP):

Terminal window
nc -u -l 127.0.0.1 9005

و در ترمینال ۲:

Terminal window
echo "پیام UDP" | nc -u -w1 127.0.0.1 9005; echo "exit=$?"
echo "پیام UDP به هیچ‌کس" | nc -u -w1 127.0.0.1 9006; echo "exit=$?"
خروجی (ترمینال ۲)
exit=0
exit=0
خروجی (ترمینال ۱)
پیام UDP

پیام اول رسید. ولی دقت کن: پیام دوم که به پورتی رفت که هیچ‌کس پشتش نبود هم با exit=0 «موفق» شد! UDP دست نمی‌دهد و تأیید نمی‌گیرد؛ فرستنده فقط پیام را انداخت و رفت (-w1 یعنی حداکثر یک ثانیه صبر کن). اینکه رسید یا نه، کار برنامه است، نه پروتکل. کارت‌پستال را انداختی در صندوق؛ نمی‌دانی رسید یا نه.

پشت پرده: پورت‌ها در سیستم‌عامل

Section titled “پشت پرده: پورت‌ها در سیستم‌عامل”

وقتی برنامه‌ای می‌گوید «می‌خواهم روی ۹۰۰۰ گوش بدهم»، از سیستم‌عامل یک سوکت (socket) می‌گیرد: یک «نقطه‌ی اتصال» که سیستم‌عامل آن را به جفت آدرس و پورت گره (bind) می‌زند. هر بسته‌ای که به کارت شبکه می‌رسد، سیستم‌عامل سرآیندش را می‌خواند، پروتکل (TCP/UDP)، آدرس و پورت مقصد را با فهرست سوکت‌ها مقایسه می‌کند و داده را به برنامه‌ی صاحب آن سوکت می‌دهد. روی هر جفت «آدرس:پورت» فقط یک برنامه می‌تواند گوش بدهد؛ اگر دومی بخواهد، خطای Address already in use می‌گیرد (رایج وقتی برنامه‌ای را دو بار اجرا می‌کنی).

TCP روی همان بسته‌های بی‌تضمین IP، «اطمینان» می‌سازد: هر بایت را شماره‌گذاری می‌کند، گیرنده برای هر چه رسید تأیید (ACK) می‌فرستد، و فرستنده هر چه تأیید نگرفت را بعد از مدتی دوباره می‌فرستد. اگر بسته‌ها جابه‌جا برسند، گیرنده با شماره‌ها مرتبشان می‌کند. برنامه‌ها از همه‌ی این پیچیدگی بی‌خبرند و فقط یک «جریان» مرتب از بایت‌ها می‌بینند.

TCP برای داده‌ای که نباید حتی یک بایتش گم شود؛ UDP برای داده‌ای که دیر رسیدنش از نرسیدنش بدتر است.
پیام معنی قدم بعدی
succeeded / open کسی روی پورت گوش می‌دهد مشکل از لایه‌ی برنامه است (رمز، تنظیم)
Connection refused به کامپیوتر رسیدی، ولی روی آن پورت/آدرس کسی نیست برنامه روشن است؟ روی کدام آدرس گوش می‌دهد؟
Connection timed out جوابی نیامد فایروال؟ IP درست؟ کامپیوتر روشن است؟
Permission denied (موقع گوش دادن) پورت زیر ۱۰۲۴ بدون دسترسی مدیر پورت بالاتر یا sudo
Address already in use برنامه‌ی دیگری روی همین پورت است ss -tln
دستور کار
nc -l 127.0.0.1 9000 گوش دادن روی یک پورت
nc 127.0.0.1 9000 وصل شدن و چت
nc -zv host port آیا پورت باز است؟
nc -u ... همان با UDP
ss -tln پورت‌های در حال گوش دادن
/etc/services فهرست پورت‌های معروف

«ping جواب می‌دهد، پس دیتابیس باید وصل شود». ping فقط می‌گوید ساختمان هست؛ دیتابیس یک واحد خاص است. راه‌حل: nc -zv سرور 5432.

refused یعنی «سریع رد شدم»: شبکه و کامپیوتر سالم‌اند، برنامه نیست. timed out یعنی «هیچ جوابی نیامد»: معمولاً فایروال یا آدرس اشتباه. دو مشکل متفاوت، دو جای متفاوت برای گشتن.

۳) گوش دادن روی 127.0.0.1 و انتظار دسترسی از بیرون

Section titled “۳) گوش دادن روی 127.0.0.1 و انتظار دسترسی از بیرون”

مثال ۵. راه‌حل: در ss -tln آدرس جلوی پورت را ببین.

۴) گوش دادن روی 0.0.0.0 بدون فایروال

Section titled “۴) گوش دادن روی 0.0.0.0 بدون فایروال”

برعکس سومی: سرویس داخلی (دیتابیس، پنل مدیریت) که روی همه‌ی آدرس‌ها گوش می‌دهد، روی سروری با IP عمومی برای کل اینترنت باز است. راه‌حل: فقط چیزی را باز کن که باید باز باشد (دوره‌ی لینوکس، درس فایروال).

۵) فکر کردن به اینکه «UDP فرستاده شد» یعنی «رسید»

Section titled “۵) فکر کردن به اینکه «UDP فرستاده شد» یعنی «رسید»”

مثال ۷. راه‌حل: با UDP، تأیید رسیدن کار خود برنامه است.

تمرینآسان

با /etc/services پیدا کن پورت‌های smtp و mysql چند هستند و کدام پروتکل (tcp/udp) را دارند. بعد بگو چرا domain (همان DNS) هر دو را دارد.

دیدن جواب
Terminal window
grep -wE "^(smtp|mysql)" /etc/services
خروجی
smtp 25/tcp mail
mysql 3306/tcp

هر دو TCP‌اند: ایمیل و دیتابیس نباید حتی یک بایت گم کنند. DNS بیشتر با UDP کار می‌کند، چون سؤال و جواب‌هایش کوچک و سریع‌اند (یک بسته رفت، یک بسته برگشت) و اگر گم شود، کلاینت فقط دوباره می‌پرسد. ولی وقتی جواب خیلی بزرگ است یا کل اطلاعات یک دامنه بین سرورها منتقل می‌شود، از TCP استفاده می‌کند.

تمرینمتوسط

با nc یک «چت» دوطرفه بساز: در ترمینال ۱ روی پورت ۹۱۰۰ گوش بده، در ترمینال ۲ بدون echo وصل شو و از هر دو طرف چند خط بنویس. بعد در ترمینال ۲ با Ctrl+C خارج شو؛ در ترمینال ۱ چه می‌شود؟ و اگر دوباره در ترمینال ۲ وصل شوی؟

دیدن جواب
Terminal window
nc -l 127.0.0.1 9100 # ترمینال ۱
nc 127.0.0.1 9100 # ترمینال ۲

هر خطی که در یکی تایپ کنی و Enter بزنی، در دیگری ظاهر می‌شود: اتصال TCP دوطرفه است. وقتی کلاینت با Ctrl+C خارج می‌شود، اتصال بسته می‌شود و nc -l در ترمینال ۱ هم تمام می‌شود و به پرامپت برمی‌گردد. اتصال دوباره:

Terminal window
nc -zv 127.0.0.1 9100
خروجی
nc: connect to 127.0.0.1 port 9100 (tcp) failed: Connection refused

nc -l فقط یک اتصال را می‌پذیرد و بعد خارج می‌شود؛ دیگر کسی روی پورت گوش نمی‌دهد. سرورهای واقعی (وب‌سرور، SSH) بعد از هر اتصال به گوش دادن ادامه می‌دهند و هم‌زمان هزاران اتصال را جواب می‌دهند. (با nc -lk هم nc بعد از هر اتصال منتظر بعدی می‌ماند؛ k یعنی keep.)

تمرینسخت

یک «سرور وب» یک‌خطی با nc بساز که به اولین مرورگری که وصل شد یک صفحه‌ی HTML بدهد. سرور را روی ۸۰۸۰ اجرا کن و با curl (یا مرورگر روی http://localhost:8080) بازش کن. پاسخ HTTP باید با خط وضعیت و یک خط خالی شروع شود.

دیدن جواب
Terminal window
printf 'HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\n\r\n<h1>سلام از nc</h1>\n' | nc -l -N 127.0.0.1 8080

در ترمینال دیگر:

Terminal window
curl -s http://localhost:8080
خروجی (ترمینال curl)
<h1>سلام از nc</h1>

و در ترمینال nc درخواست مرورگر یا curl چاپ می‌شود:

خروجی (ترمینال nc)
GET / HTTP/1.1
Host: localhost:8080
User-Agent: curl/8.5.0
Accept: */*

این یک وب‌سرور واقعی است، هرچند فقط یک بار جواب می‌دهد! پروتکل HTTP فقط متن با قالب مشخص است: خط وضعیت (HTTP/1.1 200 OK)، چند سرآیند (Content-Type، …)، یک خط خالی (\r\n\r\n)، و بعد محتوا. printf با \r\n همان «پایان خط» استانداردی را می‌سازد که HTTP می‌خواهد. همه‌ی این‌ها را در درس HTTP با جزئیات می‌بینی.

آزمونک
  1. اگر IP آدرس ساختمان باشد، پورت چیست؟

  2. پورت پیش‌فرض HTTPS کدام است؟

  3. Connection refused دقیقاً یعنی…

  4. کدام برای تماس تصویری مناسب‌تر است و چرا؟

  5. برنامه‌ای روی 127.0.0.1:8000 گوش می‌دهد. از کجا قابل‌دسترسی است؟

  6. چرا کاربر معمولی نمی‌تواند روی پورت 80 گوش بدهد؟

  • پورت (۰ تا ۶۵۵۳۵، دو بایت) داده‌ی رسیده به یک IP را به برنامه‌ی درست می‌رساند؛ پورت‌های معروف: 22، 53، 80، 443، 5432.
  • پروتکل یعنی قرارداد شکل پیام‌ها؛ داده در بسته‌ها با سرآیندهای لایه‌لایه سفر می‌کند.
  • TCP: دست‌دادن، تضمین رسیدن و ترتیب (وب، SSH، دیتابیس). UDP: سریع و بی‌تضمین (DNS، تماس، بازی).
  • Connection refused = کامپیوتر هست، برنامه روی آن پورت/آدرس نیست؛ timeout = جوابی نیامد.
  • گوش دادن روی 127.0.0.1 یعنی فقط از داخل؛ 0.0.0.0 یعنی همه‌جا (با احتیاط و فایروال).
  • nc برای آزمایش، ss -tln برای دیدن پورت‌های باز.
برگه‌ی تقلب این درس
دستورکاری که می‌کند
nc -l 127.0.0.1 9000گوش دادن (سرور)
nc 127.0.0.1 9000وصل شدن (کلاینت)
nc -zv host 22آیا پورت باز است؟
nc -u -l 127.0.0.1 9005گوش دادن UDP
ss -tlnپورت‌های TCP در حال گوش دادن
grep -w ssh /etc/servicesپورت یک سرویس
22 / 53 / 80 / 443 / 5432SSH / DNS / HTTP / HTTPS / PostgreSQL
0.0.0.0 در برابر 127.0.0.1همه‌جا در برابر فقط داخل