سرور، کلاینت و پَکِت

اینجا مفاهیم پایه networking و برنامه‌نویسی شبکه در node.js رو به زبان ساده توضیح میدم.

سرور، کلاینت و پَکِت

چند وقت پیش یه وورک شاپ خیلی خوب و جمع جور از فرانت اند مسترز دیدم که خیلی خوب شبکه سازی در Node.js رو توضیح میداد.

کلی نوت برداری کردم و خودمم کلی ریسرچ و این داستانا انجام دادم و در نهایت تصمیم گرفتم همرو تو یک سری رایت آپ جمع آوری کنم تا بقیه هم استفاده کنن.

قبل از خوندن این رایت آپ، بهتره که شما یک اطلاعاتی از مبانی شبکه داشته باشی، مثلا در این حد که با پروتکل های شبکه یکمی آشنا هستی، کلمه port به گوش ات خورده، یا اصلا به چند تا سرور ssh زدی یا برنامه نویسی انجام دادی و میدونی HTTP و HTTPS و این داستانا به چه دردی میخورن، ولی هیچوقت داخلشون عمیق نشدی و به اصطلاح knowledge gap داری.

هدف این رایت آپ اینه که اون knowledge gap هارو برای شما پر کنه.

در مجموع که اینکه من این رایت آپ رو تا حد ممکن ساده سازی کردم و هرکسی با هر سطح دانش میتونه چند تا نکته جدید ازش در بیاره و حالا اگر هیچی هم از شبکه نمیدونی، بازم میتونی ازین رایت آپ چند تا چیز یاد بگیری ولی احتمالا خودت باید یک سری کانسپت هارو سرچ بزنی و من هم سعی میکنم تا جایی که میشه راهنماییت کنم.

بررسی سرور، کلاینت و پَکِت ها

من اول میام مبانی شبکه رو از ابتدا برات توضیح میدم، این چپترو با دقت بخون تا درک بهتری از شبکه پیدا کنی.

به هر دیوایسی که در شبکه توانایی ایجاد، دریافت، ذخیره کردن یا انتقال دیتا رو داره، یک node گفته میشه، ولی خب لفظ machine هم داخل متون آکادمیک پر کاربرد هست و من از همه اینا اینجا استفاده میکنم که شما عادت کنی. ماشین منظورم هر دیوایسی هست که توانایی compute کردن داره، مثل لپتاپ، موبایل، رزبریپای و غیره.

در اولین قدم میخوام روشن کنم که تو این رایت آپ، منظور من از سرور و کلاینت چیه؟ احتمالا هر موقع صحبت سرور میشه شما احتمالا یه همچین تصویری تو ذهنت میاد:

Pasted image 20260709192401.png

که شاید تصویر درستی هم هست، معمولا وقتی از سرور صحبت میشه معمولا منظور همین rack ها هستن، ولی تو این رایت آپ منظور من از سرور یه همچین چیزیه:

Pasted image 20260709192413.png

در واقع هر ماشینی که داخل شبکه هست میتونه یک سرور باشه، یا یه کلاینت باشه، یا هردوی اینا باشه!

یعنی آیه نیومده که شما حتما باید یک سرور فضایی داشته باشی و همین موبایل یا لپتاپی که داری این رایت آپو باهاش میخونی میتونه تبدیل یک سرور بشه و دیتا جا به جا بکنه.

کلاینت هم اون ماشینی هست که به یک سرور متصل میشه.

یک نوع متفاوتی از شبکه هم هست که به اسم peer-to-peer شناخته میشه، و توی شبکه peer-to-peer ، همه ی node ها همزمان هم کلاینت هستن هم سرور، یعنی سرور مرکزی وجود نداره و کلاینت ها مستقیما به همدیگه وصل میشن. مثلا پروتکل bittorrent یا فریموورک webrtc از معروف ترینا هستن.

حالا این اطلاعات چجور داخل جا به جا میشن؟

این عکسو پایینو با دقت نگاه کن تا بعد برات توضیح بدم:

91d77861-5141-4435-b434-d374bd1490e8.png

اینجا چی داره میشه؟ خب اون دیتایی که تو میخوای بفرستی معمولا یک چیز خیلی چاق و چله ای هست و اینطوری نیست که به صورت یکجا توی شبکه منتقل بشه، بلکه به قطعه های کوچولو کوچولو ( packet ) تقسیم میشه و بعد این پکت ها از زیر دست دیوایس ها و نتوورک های مختلف عبور میکنن تا به مقصد برسن، این پکت ها در مقصدشون دوباره reassebmle میشن و دیتای اولیه بدست میاد.

مثلا پروتکل TCP که الان بررسیش میکنیم، میاد هر کدوم یک از این پکت ها، یدونه sequence number میده که شماره توالی اون پکت محسوب میشه، سرور میاد بر اساس اون sequence number دیتا رو reassemble میکنه.

اگه میخوای بیشتر تو این مبحث عمیق بشی، برو در مورد لایه های شبکه ریسرچ انجام بده، میتونی از هفت خان رستم شروع کنی که خودم نوشتمش. خلاصه اینکه دو مدل شبکه وجود داره که اولی مدل هفت لایه ( OSI ) هست و دومی مدل چهار لایه ( TCP/IP ) هست و این دوتا مکمل هم هستن. من برای اینکه از بحث منحرف نشم، اینجا زیاد واردشون نمیشم.

بعد پروتکل های مختلفی وجود داره که میاد دیتارو داخل شبکه برای ما جا به جا میکنه که دو مورد مهم ترینش TCP که الان بهش اشاره کردم و اون یکی UDP هست و اینا مسئولیت انتقال دیتارو به عهده دارن.

تاکید میکنم کار TCP و UDP اینه که دیتارو داخل شبکه برای جا به جا کنن، اگه نوبی، کافیه که همین تصویر ساده تو ذهنت باشه و لازم نیست از اسم این پروتکل ها بترسی چون به مرور زمان برات عادی میشن.

اول بیا اتصال TCP رو بررسی کنیم. یه دقه این دیاگرام رو یه نگاهی کلی بنداز:

baa65ecd-d62f-4258-a358-3211cc368cd6.png

الان شما میدونی که TCP میاد و دیتا رو داخل شبکه جا به جا میکنه، درسته؟ داخل این دیاگرام هم دقیقا داری میبینی که TCP چطور این کارو انجام میده. ( لازم نیست کل دیاگرام رو متوجه بشی، صرفا میخواستم چشمت به این کانسپت ها خورده باشه )

کانکشن TCP ذاتا یک کانکشن reliable یا قابل اتکا محسوب میشه و به عبارتی TCP اطمینان حاصل میکنه که همه پکت ها صحیح و سالم به مقصد میرسن. حالا چطور این کارو انجام میده؟

تی سی پی اول از همه میاد یه هندشیک بین کلاینت و سرور انجام میده و مطمئن میشه که هر دو طرف داستان آماده برقراری ارتباط هستن.

هندشیک TCP یه تبادل اطلاعات خیلی کوتاه و جمع و جور بین سرور و کلاینته که با ارسال سه تا پکت مخصوص بین سرور و کلاینت انجام میشه و بعدش اتصال TCP برقرار میشه، همینقدر بدونی فعلا کافیه.

بعدش TCP میاد و دیتا رو به قطعه های کوچولو تقسیم میکنه که از قبل بهش اشاره کردیم و میدونیم که به اون قطعه های کوچولو میگن packet ، و به هر پکت هم یک sequence number تعلق میگیره که بعدا در مقصد برای reassemble کردن دیتا مورد استفاده قرار میگیره.

حالا TCP به ازای هر یدونه پکتی که میفرسته، منتظر acknowledgment یا همون ACK از سمت مقصد میمونه تا مطمئن بشه که پکت صحیح سالم به مقصد رسیده. اگه TCP این ACK رو دریافت نکنه، پکت رو دوباره و دوباره میفرسته ( حالا این یه سری لیمیت داره ولی شما کانسپتو یاد بگیر و دنبال زیر بغل مار نگرد )

فعلا ما یاد گرفتیم که TCP یک کانکشن reliable هست و مطمئن میشه که پکت ها کامل ارسال شدن.

بیا بریم یه نگاه به پروتکل UDP بندازیم:

890aaeed-477b-489c-90a5-20723902e8b7.png

اینجا میبینی که از یک سری جهات UDP و TCP شبیه هم هستن و جفتشون یک سری پکت رو جا به جا میکنن، ولی خب فرقشون اینه که مثلا UDP اون هندشیک اولیه رو نداره و بعد هم منتظر ACK نمیمونه.

یعنی این UDP هم دیتا رو به صورت پکت منتقل میکنه، ولی برخلاف TCP خودش هیچ مکانیزمی برای شماره گذاری و ACK و این داستانا نداره.

به عبارتی، کانکشن UDP فقط به صورت الله بختکی یک سری پکت رو شوت میکنه سمت مقصد و براش مهم نیست که آیا اون پکت به مقصد میرسه یا نه.

الان شاید با خودت فکر کنی این پروتکل خیلی تخیلیه، ولی اتفاقا توی خیلی از سناریو ها کاربردیه. مثلاً فرض کن داری یه مسابقه فوتبال رو به صورت لایو می‌بینی و کیفیت اینترنتت یه لحظه افت می‌کنه و چند تا پکت اون وسط دراپ میشن. تو نمی‌خوای پخش ویدیو متوقف بشه تا اون پکت‌ها دوباره ارسال بشن، حالا حتی اگه چند فریم یا چند لحظه از بازی رو از دست بدی، ترجیح میدی سریع آخرین تصویر و فریم رو ببینی تا اینکه استریم عقب بیفته یا مدام بافر کنه.

توی کتب آکادمیک یه سری مثال ها زده میشه که امروز دیگه خیلی دقیق نیستن، مثلا میگن که از UDP برای DNS queries استفاده میشه ولی من تحقیق کردم و این کاملا دقیق نیست چون امروزه مرورگر ها بخاطر امنیت اکثرا از DoH یا DNS over HTTPS استفاده میکنن که کانکشن TCP هست. اگه خواستی بیشتر بدونی برو رایت آپ DNS منو بخون. مثال مشابه هم زیاد هست ولی خب هرجا خوندید که فلان جا داره از UDP استفاده میکنه حتما خودتون هم یک دبل چک بزنید.

خب شما تا اینجا یاد گرفتی که TCP و UDP چیه و چکار میکنن، حالا غیر از این دوتا پروتکل های دیگه ای هم هستن، به فرض پروتکل ICMP که برای گزارش وضعیت شبکه ازش استفاده میشه، مثلا دستور ping از پروتکل ICMP استفاده میکنه.

فعلا تا همین حد بدونی کافیه.

بررسی دقیق تر پروتکل ها

تو قسمت قبل من اومدم به شما گفتم که TCP و UDP پروتکل هایی هستن که پکت هارو بین دو تا ماشین جا به جا میکنن.

ولی بیا همین کلمه پروتکل رو بیشتر بررسی بکنیم و ببینیم منظور ما از پروتکل چیه.

مثلا ما آدم ها از زبان یا همون language برای انتقال منظورمون استفاده میکنیم، حالا شاید شما بخوای با یک آدم ژاپنی صحبت کنی و نه شما ژاپنی میفهمی و نه اون طرف فارسی میفهمه.

در نتیجه معمولا شما جفتتون از یک زبان مشترک استفاده میکنین و مثلا شروع میکنین به انگلیسی حرف زدن و زبان انگلیسی میشه پروتکل ارتباطی بین شما دو تا.

خب ماشین ها هم به همین شکل هستن و به یک زبان مشترک نیاز دارن که حرف همو بفهمن، و این زبان مشترک همان پروتکل هست.

اینجا یه سیخونک به مدل OSI میزنم، تعداد زیادی پروتکل در لایه های مختلف شبکه هست که هر کدوم وظایف متفاوتی دارن. مثلا پروتکل های TCP و UDP داخل لایه ۴ یا همون Transport Layer هستن، در حالی که مثلا HTTPS یک پروتکل در لایه ۷ ( Application Layer ) هست. این شاید الان یکم برات گیج کننده باشه ولی کم کم بهش عادت میکنی. پس حواست باشه که پروتکل ها شاید در لایه های مختلف باشن و کار های کاملا متفاوتی رو انجام بدن، و نمیتونی هر موقع اسم پروتکل رو شنیدی سریع اونو بذاری کنار TCP و UDP ، بلکه باید ببینی اون پروتکل تو کدوم لایه اس و چکار میکنه.

مثلا شما حتما پروتکل HTTP رو شنیدی و میدونی ازین پروتکل برای رد و بدل کردن صفحات وب استفاده میشه، یا HTTPS که یک لایه encryption به HTTP اضافه میکنه تا کسی نتونه ترافیک شمارو ببینه.

دقیق تر بخوام بگم، HTTPS در واقع HTTP هست که روی TLS اجرا میشه.

چند تا پروتکل پرکاربرد دیگه هم بخوام مثال بزنم:

  • پروتکل SMTP که برای ارسال ایمیل استفاده میشه.
  • پروتکل FTP که برای انتقال فایل استفاده میشه و الان نسبتا منسوخ شده، ولی هنوز بعضی جاها استفاده میشه.
  • پروتکل SSH برای اتصال ریموت و رمزنگاری شده به یک کامپیوتر دیگه.
  • پروتکل SSL برای رمزنگاری دیتا که حالا امروز دیگه همه TLS استفاده میکنن و هرجا میگن SSL منظورشون همون TLS هست.

الان شاید برات سوال شه که کامپیوتر ما چطور از همه پروتکل های بالا پشتیبانی میکنه؟

خب یک کامپیوتر از port numbers استفاده میکنه تا چندین network service رو هم‌زمان اجرا کنه. همون‌طور که مثلا IP Address مشخص می‌کنه پکت به کدوم کامپیوتر بره، port number مشخص می‌کنه این پکت به کدوم سرویس روی اون کامپیوتر تحویل داده بشه.

مثلاً اگه بخوایم یه صفحه‌ی وب درخواست کنیم، معمولاً به سرویسی که روی پورت ۴۴۳ هست وصل می‌شیم، یا اگه بخوایم یه remote shell داشته باشیم، معمولاً به پورت ۲۲ وصل می‌شیم.

بررسی ابزار netcat

خب حالا میخوایم شروع کنیم و چند تا تسک عملی انجام بدیم، این ابزار netcat خیلی خوبه و به ما اجازه میده که به صورت plain ‍text یک session بین کلاینت و سرور ایجاد کنیم

خب اگه netcat رو نصب نداری همین الان برو رو سیستمت نصبش کن.

بعد این دستور رو داخل یک صفحه ترمینال بزن:

nc -l 5000

اگه ارور داد اینو بزن، netcat رو بعضی سیستم عامل ها متفاوت عمل میکنه و بالاخره یکی ازین دو تا کامند باید اجرا شه:

nc -lp 5000

حالا یه ترمینال جدید باز کن و اینو بزن:

nc localhost 5000

به همین راحتی شما یک port روی کامپیوترت باز کردی و با استفاده از netcat بهش وصل شدی! نتیجه نهایی یه چت اپ خیلی ساده اس: 71BF383A-80E5-4983-A436-58D09497A2DD.gif

خود netcat هیچ پروتکلی رو پیاده سازی نمیکنه و فقط بایت هارو بین دو اتصال TCP یا UDP جابه‌جا میکنه، و در واقعیت کار خیلی پیچیده تر از این حرفاس و اینجا ما از پروتکل خاصی استفاده نکردیم و امنیت هم که رو هواس، همه چی اینجا plain text هست و هر کسی داخل شبکه میتونه محتوای چت رو بخونه!

پس بیا بریم نقش پروتکل هارو بیشتر بررسی بکنیم.

معرفی HTTP و بررسی پروتکل های text-based

این HTTP یک پروتکل text-based برای ارتباط بین سرور و کلاینته، و تعیین میکنه که request و response چطور بین این سرور و کلاینت رد و بدل بشه.

منظور از text-based اینه که HTTP خیلی human-readable هست و شما با نگاه کردن به یک HTTP request یا HTTP response میتونی به سادگی متوجه بشی که چه اتفاقی داره میفته.

البته شما گول سادگی HTTP رو نخورید، اتفاقا بنظرم HTTP پروتکل عمیق و پیچیده ای هست و من اینجا قصد دارم فقط سرنخ بهت بدم، و خودت باید بری کمی عمیق تر بشی بعدا.

توی چنل تلگرامم یه پست گذاشتم که بنظرم میتونه نقطه شروع مناسبی باشه، ازینجا شما میتونی کم کم توی HTTP عمیق بشی.

Pasted image 20260709192626.png

حالا همونجور که داشتم میگفتم، پروتکل HTTP کاملا text-based هست و یک سری method یا verb داخلش هست که برای کار های مختلف استفاده میشه و شما باید یادشون بگیری، مثلا GET که برای دریافت اطلاعات استفاده میشه، یا POST که برای ارسال اطلاعات استفاده میشه، یا HEAD که برای دریافت متادیتای یه document روی وب سرور استفاده میشه.

حالا PUT و OPTIONS و DELETE اینا هم هستن و در کل شما باید بری اینارو حفظ کنی و بلد باشی، اینجا فعلا در abstract یاد بگیر کهHTTP verb یا همون HTTP methods چیه و به چه درد میخوره.

اینم بگم که برنامه نویسا معمولا قیمه هارو میریزن تو ماستا و از verb های اشتباه استفاده میکنن، یعنی HTTP اینجوری نیست که بیاد گیر بده که مثلا داری یه ریسورسی رو دیلیت میکنی و حتما باید از متود DELETE استفاده کنی، و برنامه نویس شاید بیاد همه چیو کلا با متود POST هندل کنه، من خودم ازین کارا زیاد کردم.

بعد خب یک سری اطلاعات اضافه‌ای هم هستن که همراه هر HTTP request و HTTP response ارسال می‌شن و به دو طرف داستان کمک می‌کنن بدونن چطور باید با هم ارتباط برقرار کنن.

به این اطلاعات اضافه میگن HTTP Headers .

این هدر ها می‌تونه شامل نوع دیتا (Content-Type)، هویت کاربر (Authorization)، کوکی‌ (Cookie) یا نحوه‌ی کش شدن (Cache-Control) و غیره باشه.

حالا در ادامه توضیح میدم که خودِ body عه که دیتا رو حمل می‌کنه، ولی هدر فقط اطلاعات و تنظیمات مربوط به اون دیتا رو منتقل می‌کنن.

مثلا یه مثال ساده این پایین میزنم که جا بیفته: B9DDEB5E-2D06-46AF-A23A-4D3140DA4BB5.gif

اینجا من یه درخواست به سرور گوگل میزنم، و در واقع با هدر Host ، به سرور گوگل میگم که من خود گوگل دات کام رو میخوام، در نظر داشته باش که سرور گوگل شاید صد ها سرویس مختلف رو میزبانی بکنه و بیاد ازین هدر Host استفاده کنه تا سرویس مورد درخواست کاربر رو بهش بگردونه.

به این کار می‌گن virtual hosting و تقریبا همه‌ جا ازش استفاده می‌شه. بعد ازونور هکرها میان و کلی درخواست با Host header های مختلف سمتِ یک سرور می‌فرستن، به امید این‌ که یه اپلیکیشن آسیب‌پذیر روی اون وب‌سرور پیدا کنن.

اینجا میبینی که گوگل یه ریسپانس با استاتوس کد 301 بهم برگردونده، حالا status code یعنی چی؟

این status code ها یک سری عددهایی هستن که سرور در جواب یک HTTP request برمی‌گردونه تا نتیجه‌ی درخواست رو به کلاینت اعلام کنه.

مثلا 200 OK یعنی درخواست موفق بوده، 404 Not Found یعنی منبع پیدا نشده، و 500 Internal Server Error یعنی روی سرور مشکلی پیش اومده.

این استاتوس کد یه عددی بین 100 تا 599 عه و هرکدوم یه معنایی دارن، شما به مرور زمان اینارو یاد میگیری و حالا میتونی بری اینجا و ببینی هرکدوم چه معنایی دارن و حفظشون کنی.

مثلا همین بالا دیدی که گوگل یه ریسپانس با استاتوس 301 به من داد، 301 یعنی که اون ریسورسی که دنبالشی برای همیشه به یک آدرس جدید منتقل شده.

مثلا ما google.com رو درخواست کردیم و سرور گوگل به ما گفت که google.com برای همیشه به www.google.com منتقل شده، حالا خود کمپانی گوگل تصمیم گرفته که سرور همچین رفتاری داشته باشه و ما اینجا واردش نمیشیم.

ولی خب اینجا ما با netcat درخواستو زدیم و ریسپانسو دیدیم ولی شما اگه داخل مرورگر این google.com رو بزنی میبینی که خودش به صورت اتوماتیک، ریدایرکت رو دنبال میکنه و www.google.com رو به شما نشون میده.

81B84DAB-3A00-4FD5-9038-7CF4208DA0DF.gif خب حالا بیا متود POST هم یه بررسی بکنیم، من اینجاها از کد های خود وورکشاپ استفاده میکنم چون خیلی خوب و سرراسته و توضیحات رو از خودم اضافه میکنم.

اینجا به‌صورت کلی میتونی ببینی که یک HTTP server چطور یک HTTP request رو دریافت می‌کنه، اطلاعاتش مثل headers و body رو می‌خونه و پردازش می‌کنه، و در نهایت یک HTTP response به client برمی‌گردونه:

var http = require('http')
var parseform = require('body/any')

var server = http.createServer(function (req, res) {
  console.log(req.method, req.url, req.headers)
  parseform(req, res, function (err, params) {
    console.log(params)
    res.end('ok\n')
  })
})
server.listen(5000)

درخواست POST ما هم این شکلیه و داخل فایل post.txt هست:

POST /form HTTP/1.1
Host: localhost
Content-Length: 51
Content-Type: application/x-www-form-urlencoded

title=whatever&date=1421044443&body=beep%20boop%21

تو همین مثال میتونی ببینی که چطور هدر ها قبل از body ارسال می‌شن و به سرور می‌گن چطور باید درخواست رو تفسیر کنه. مثلاً:

  • هدر Host: localhost داره میگه که این درخواست برای localhost ارسال شده.
  • هدر Content-Length داره میگه که بدنه ی درخواست دقیقا ۵‍۱ بایت دیتا داره، پس سرور میدونه که چقدر از body رو باید بخونه.
  • هدر Content-Type داره فرمت body رو مشخص میکنه و میگه که دیتا به شکل key=value&key=value ارسال شدن.

حالا با استفاده از دستور netcat ما درخواست رو اجرا میکنیم:

nc localhost 5000 < post.txt

و نتیجه نهایی هم اینجا میتونی ببینی: 2C57A44D-0364-4803-9B0C-3F3810CA199D.gif

خب بنظرم فعلا همینقدر از HTTP بدونی و کافیه، و اینکه ما معمولا با netcat درخواست HTTP نمیزنیم بلکه از کامند دیگه ای به اسم curl استفاده میکنیم که در ادامه قراره برات بررسیش کنم.

معرفی کامند curl

این curl به احتمال زیاد آلردی رو سیستمت نصبه، چون یک ابزار استانداردی هست و زیاد استفاده میشه.

این curl یک ابزار داخل کامندلاین هست که بهت اجازه میده مستقیما از ترمینالت به یک سرور HTTP request بزنی و ریسپانس رو هم همونجا ببینی. ( البته که پروتکل های دیگه هم ساپورت میکنه )

مثلا شما میتونی با استفاده از این دستور:

curl https://divar.ir/

مستقیما به divar.ir درخواست بزنی و ریسپانسو تو ترمینالت ببینی: Clipboard-20260710-215452-591.gif

اینجا میتونی ببینی که من با استفاده از دستور curl یک درخواست به divar.ir زدم و دیوار هم که ریسپانس بهم داد که حاوی کد HTML ئه، این همون کدی هست که مرورگر برات parse میکنه و بعد شما میتونی محتوای سایت رو داخل مرورگرت ببینی، و خب چون ما اینجا داخل ترمینال هستیم طبیعتا فقط میتونیم کد HTML رو ببینیم. یعنی حالا درسته که دیدن HTML داخل مرورگر ساده تره، ولی هدف ما این نیست که محتوای یک سایت رو با curl ببینیم، بلکه curl کارایی دیگه ای داره.

مثلا شما شاید بخوای هدر های یک سایت رو بررسی کنی و اینکار با curl خیلی ساده تره:

curl -I https://divar.ir/

با اضافه کردن فلگ I ، دستور curl فقط header هارو برات برمیگردونه که یک چیزی مشابه این هست: ‍

HTTP/2 200
date: Fri, 10 Jul 2026 22:04:54 GMT
content-type: text/html; charset=utf-8
content-length: 114657
vary: Accept-Encoding
x-dns-prefetch-control: on
expect-ct: max-age=0
x-frame-options: DENY
strict-transport-security: max-age=31536000
x-download-options: noopen
x-content-type-options: nosniff
x-permitted-cross-domain-policies: none
referrer-policy: origin
x-xss-protection: 1; mode=block
etag: W/"1bfe1-tl47/JUFcblhUVHH+KJ0fxEAvfg"
x-envoy-upstream-service-time: 18
x-datacenter: hwb
x-zrk-us: 200
x-zrk-cs: BYPASS
server: Sotoon CDN
x-zrk-sn: 2002
accept-ranges: bytes
accept-ranges: bytes

این مثلا زمانی به کار میاد که شما داری یک HTTP server رو دیباگ میکنی و فقط میخوای هدر هارو چک کنی، و نمیخوای هی بری داخل dev tools مرورگرت و در عوض با curl راحت میتونی کارو در بیاری.

بعد شما میتونی از HTTP method های مختلف هم استفاده بکنی و با همین curl درخواست POST و DELETE و اینا هم بزنی.

مثلا همون مثال POST که بالاتر با netcat زدم رو بیا با curl هم پیاده سازی کنیم:

curl -X POST http://localhost:5000 -d title=whatever

اینجا با استفاده از فلگ X میایم و HTTP method رو مشخص کردیم که POST هست، و بعد URL رو بهش دادیم و بعد هم با استفاده از فلگ d اومدیم و data رو بهش دادیم. نتیجه هم این شد:

Screenshot 2026-07-11 at 1.45.40 AM.png

مقصود حرفم اینه که شما هرکاری که به فکرت میرسه میتونی با curl انجام بدی و تقریبا محدودیتی نداری، من اینجا در حد نیازت بهت توضیح دادم ولی اگه دوست داری بیشتر عمیق بشی میتونی بری و داکیومنتیشن خود curl رو یه نگاهی بندازی.

خب الان شما آشنایی نسبی با پروتکل HTTP پیدا کردی و یاد گرفتی که چطور با curl درخواست های HTTP بفرستی،

حالا درسته که HTTP خیلی راحت خونده میشه، ولی چون text-based هست، حجمش زیاده و پردازش text هم هزینه بیشتری داره. برای همین بعضی پروتکل ها به جای text، ساختار مشخصی از بایت ها ارسال میکنن تا هم حجم کمتر بشه و هم پردازش سریع تر انجام بشه.

اینجاست که پروتکل های binary وارد ماجرا میشن.

نسخه اولیه این رایت آپ شامل پروتکل های text-based دیگه ای مثل SMTP و IRC هم میشد، ولی احساس کردم حجم رایت آپ خیلی زیاد شده و تصمیم گرفتم فقط HTTP که پرکاربرد تر هست رو اینجا پوشش بدم، و بعدا دو تا رایت آپ جدا راجع به SMPT و IRC بنویسم. حالا اگه خودت دوست داشتی میتونی بری در مورد این پروتکل ها هم مطالعه کنی.

معرفی SSH و بررسی پروتکل های binary

پروتکل های binary میان و دیتا رو به‌ جای تکست، به‌صورت ‍raw bytes جابه‌جا میکنن. هر بایت (یا یه گروه از بایت ها) یه معنی مشخص داره که از قبل توی protocol تعریف شده، واسه همین کلاینت و سرور باید دقیقاً روی فرمتش با هم هماهنگ باشن. اگه یکی از این دو طرف، بیاد و اون بایت هارو یه جور دیگه تفسیر کنه، عملاً دیگه دارن دو تا زبان متفاوت حرف می‌زنن و کانکشن به فنا میره.

یعنی دارم میگم که در یک binary protocol، همه‌چیز از قبل بین کلاینت و سرور هماهنگ شده و بر فرض مثال، هر دو می‌دونن که بایت اول نوع message رو مشخص می‌کنه، بایت دوم طول username رو میگه و چند بایت بعدی خود username هست. در نتیجه وقتی یه سری بایت ارسال میشه، سرور دقیقاً می‌دونه هر قسمت چه معنی‌ای داره.

اصلا بذار با مثال بهت بگم، این درخواست رو در نظر بگیر:

LOGIN yazdan password123

‍‍‍ اگه اینو بخوای با یه پروتکل باینری بفرستی، تبدیل به همچین چیزی میشه:

01 06 79 61 7A 64 61 6E 0B 70 61 73 73 77 6F 72 64 31 32 33

اینجا ما یک سری اعداد هگزادسیمال داریم و مثلا 01 یعنی LOGIN ، بعد 06 میشه طول username ، پس 6 تا بایت بعدی میشن خود username، بعد 0B میشه طول پسوورد و بقیه بایت ها هم میشن خود پسوورد.

خود این بایت ها هیچ معنی خاصی ندارن و فقط چون هر دو طرف از یه protocol specification مشترک پیروی می‌کنن، می‌تونن اونارو درست تفسیر کنن.

هگزادسیمال (Hex) فقط یه روش دیگه برای نوشتن اعداده. ما توی زندگی روزمره از سیستم ده‌ دهی (0 تا 9) که تو دبستان یاد گرفتیم استفاده می‌کنیم، ولی توی هگز ۱۶ تا نماد داریم: 0 تا 9 و بعدش A تا F که به‌ترتیب معادل 10 تا 15 هستن. چون ماشین ها دیتا رو به صورت بایت ذخیره می‌کنن، معمولا هر بایت رو با دو رقم هگز نمایش می‌دن، و کلا هگز یه روش جمع‌وجور و راحت برای دیدن بایت‌ های خام کامپیوتره.

اینجوری با ارسال باینری، دیتا compact میشه و bandwidth کمتر میشه و خب خوندن دیتای binary برای ماشین ها ساده تره و سریع تر میتونن اون دیتارو process کنن.

بعد آها اینجا بحث encryption هم میاد وسط و وقتی شما یک دیتایی رو میفرستی سمت سرور، این دیتا با جادو جمبل به سرور نمیرسه و برعکس از زیر دست کلی دیوایس مختلف عبور میکنه، پکت های شما چندین و چند بار بین این دیوایس ها فروارد میشن تا به مقصد برسن.

مثلا اگه شما به صورت مستقیم از HTTP استفاده بکنی، هر کدوم از این دیوایس ها میتونن ترافیک شمارو بخونن و مثلا ISP شما میتونه بیاد و همه یوزرنیم و پسوورد و کوکی های شمارو بخونه، که اصلا چیز ایده آلی نیست! برای همین هیچوقت نباید با خود HTTP داخل یک وبسایت لاگین کنی و اصلا برای همینه که مرورگر ها اینقدر سر SSL certificate گیر هستن و میگن که حتما باید با HTTPS وصل بشی که secure و encrypted هست.

الان پروتکل SSH یه مثال خوب از یه binary protocol هست. SSH یا همون Secure Shell یه network protocol برای برقراری یه ارتباط امن بین کلاینت و سرور هست. وقتی با SSH به یه سرور وصل میشی، اول همون handshake اولیه انجام میشه تا دو طرف هویت همدیگه رو بررسی کنن و بعد روی یه shared encryption key به توافق برسن. بعد از اون، تمام اطلاعات مثل commands، خروجی ترمینال و فایل‌هایی که جابه‌جا میشن قبل از ارسال encrypt میشن و به‌صورت binary packets روی شبکه رد و بدل میشن.

این یعنی حتی اگه کسی ترافیک شبکه رو capture کنه، فقط یه سری بایت های رمزنگاری شده و غیرقابل خوندن می‌بینه و نمی‌تونه بفهمه داخل اون ارتباط چه داده‌ای رد و بدل شده.

پس به‌جای اینکه چیزی مثل LOGIN username به‌صورت تکست ارسال بشه، SSH یه سری binary field می‌فرسته که اطلاعاتی مثل packet type، packet length، encrypted data و integrity check رو داخل خودشون دارن و چون هم کلاینت و هم سرور از SSH protocol پیروی می‌کنن، دقیقاً می‌دونن هر byte چه معنی‌ای داره و چطور باید تفسیرش کنن.

اینم بگم که بحث encryption یه موضوع جدا از binary یا text-based بودن پروتکله. مثلا توی SSH، اول کلاینت و سرور میان یه key exchange انجام میدن تا روی یه shared encryption key به توافق برسن.

بعد از اون، هر binary packet قبل از ارسال encrypt میشه. یعنی اول SSH یه binary packet با ساختار مشخص می‌سازه، بعد همه‌ی byteهاش رو به یه سری byte رمزنگاری شده و غیرقابل خوندن تبدیل می‌کنه و روی شبکه می‌فرسته.

سمت مقابل هم با همون shared key، اون bytes رو decrypt می‌کنه و دوباره به همون binary packet اولیه برمی‌گردونه.

برای اینکه دیتای باینری رو با encryption قاطی نکنی یکم بیشتر توضیح میدم: binary protocol فقط مشخص می‌کنه بایت ها چطور کنار هم چیده بشن و هر کدوم چه معنی‌ای داشته باشن، ولی encryption همون bytes رو قبل از انتقال، رمزنگاری می‌کنه. یعنی SSH اول binary packet رو می‌سازه، بعد encryptش می‌کنه، از طریق TCP می‌فرسته و سمت مقابل دوباره decryptش می‌کنه و بعد تازه شروع می‌کنه به تفسیر کردنش. پس چون صرفا دیتا به شکل باینری هست و شما نمیتونی بخونیش به این معنی نیست که امنه و لایه encryption کاملا جدا هست و صرفا چون یک پروتکل binary هست به معنای امن بودنش نیست.

خب فعلا همینقدر از SSH و پروتکل های باینری بدونی کافیه و من در قسمت های بعدی بیشتر برات بازشون میکنم.

جمع بندی

در این رایت‌آپ سعی کردم به جای قطار کردن اسم پروتکل ها، بیام و اول طرز فکر پشت شبکه رو بهت بگم. مثلا فهمیدیم که سرور و کلاینت صرفا دو تا node داخل شبکه هستن، دیتا برای انتقال به قطعه‌ های کوچیک تر تقسیم میشه، تفاوت TCP و UDP چیه و چرا هر کدوم برای سناریوهای متفاوتی طراحی شدن.

بعد دیدیم که منظور از خود کلمه پروتکل در یک شبکه، در واقع یک زبان مشترک بین دو ماشینه.

بعد از اون با netcat اولین شبکه خودمون رو ساختیم و بعد با HTTP و ساختار request و response آشنا شدیم، headers، status codeها و HTTP methods رو بررسی کردیم و دیدیم که curl چطور میتونه برای دیباگ کردن و ارسال درخواست‌های HTTP به کارمون بیاد.

اون آخر هم تفاوت پروتکل‌های text-based و binary رو دیدیم.

خب اولین قسمت از رایت آپ برنامه نویسی شبکه، همینجا تموم میشه و در قسمت بعدی در مورد stream ها برات مینویسم.

تا اون موقع از خودتون مراقبت کنید، روزانه یک ربع ورزش کنید و هشت لیوان آب بنوشید. فعلا خدافظ.