Pooria Setayesh
Pooria Setayesh
خواندن ۱۵ دقیقه·۴ سال پیش

ساخت وب سرور استاتیک با سی شارپ

مایکروسافت ویژوال استودیو

ویژوال استودیو نام یک IDE محبوب از شرکت مایکروسافت است برای تولید انواع نرم افزارهای تحب وب ، موبایل و ویندوز

اولین ورژن ویژوال استودیو در سال ۱۹۹۷ منتشر شد که نام آن ویژوال استودیو ۹۷ و ورژن آن 5.0 بود. جدیدترین نسخه ویژوال استودیو 2019 تحت عنوان ویژوال استودیو 2019 به طور عمومی منتشر شد. دات نت فریم ورک پشتیبانی شده در این نسخه 4.0 تا 4.7.2 است.

قابلیت های نرم افزار مایکروسافت ویژوال استودیو

· مدیریت نرم افزار در طول چرخه ی حیات آن

· سیستم گزارش باگ و اشکال زدایی

· آنالیز کردن کد های نوشته شده

· اجرای تست دستی، توانایی تست خودکار UI در برنامه های تحت وب یا ویندوز

· اجرای تست عملکرد (Performance Testing)، تست بار گذاری (Load Testing)

· مدل سازی و دستیابی به تعدادی از کدهای موجود و توابع وابسته آن

· مدیریت و گسترش پایگاه داده همزمان با اعمال تغییرات کد

· طراحی نرم افزار جدید و یا افزایش کد های نوشته شده ی قبلی

· قابلیت multi-monitor به منظور مدیریت و سازماندهی بهتر

· نوآوری های و امکانات جدید در زبانهای C# و Visual Basic ایجاد شده است.

· امکاناتی در ASP.NET برای کنترل نمودارها و استفاده از تکنولوژی AJAX پیاده سازی شده است.

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

به نظر من کنسول اپلیکیشن بهترین تکنولوژی و محیط برای آموزش زبان برنامه نویسی مثل سی شارپ هست چون مخاطب زیاد درگیر پیچیدگی های تکنولوژی هایی مثل Windows Form یا Asp.Net MVC نخواهد شد چون خود این تکنولوژی ها نیازمند آموزش جداگانه هستند.

در زمان های دور، کامپیوترها به اندازه الان پیشرفت نکرده بودند. چیزی به نام ویندوز یا دیگر سیستم عامل های پیشرفته وجود نداشت. یا چیزی به نام گرافیک تصویری در کامپیوتر، معنا نداشت. یعنی شما فقط می توانستید با استفاده از صفحه کلید(Keyboard) ، دستورات مدنظر خودتون رو به کامپیوتر انتقال دهید و در نهایت کامپیوتر نتایج اجرای دستورات شما رو بصورت یک سری متن و نوشته، در یک صفحه با پس زمینه سیاه به نمایش در می آورد. البته در سالیان دور همین نمایش متن و نوشته، بر روی مونیتور (Monitor) ، خودش انقلابی در صنعت کامپیوتر و الکترونیک بود.

سی شارپ

سی شارپ زبانی شیءگرا و سطح بالا از خانواده ی زبان‌های چارچوب دات‌نت شرکت مایکروسافت است.

این زبان توسط مایکروسافت و جزئی از دات نت به وجود آمد و بعداً استانداردهای ECMA و ISO را نیز دربر گرفت.

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

این زبان برپایه سادگی، مدرن بودن، همه منظوره و شیءگرا بودن ساخته شده است.

آندرس هجلزبرگ، طراح زبان برنامه‌نویسی دلفی، سرپرستی تیم طراحان زبان سی شارپ را بر عهده داشت. این زبان دارای دستورات شیءگرا مشابه زبان سی پلاس پلاس است و به شدت به زبان‌ جاوا شباهت دارد.

در ابتدا نام این زبان COOL بود که مخففC like Object Oriented Language بود، هر چند در ژوئیه ۲۰۰۰، زمانی که مایکروسافت پروژه را عمومی اعلام کرد، اسم آن به سی شارپ تغییر پیدا کرد.

در مورد طراحی HttpServer

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

پروتکلHttp به چه معناست؟

قبلا روش استانداردی یا پروتکل استنداردی برای رد و بدل اطلاعات در اینترنت وجود نداشت.

به همین دلیل آقای Tim Berners-Lee در سال 1991 پروتکل Http را برای اینکه یک روش استاندارد برای رد و بدل اطلاعات وجود داشته باشد پیاده سازی کرد.

روش‌های درخواست در پروتکل http

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

ولی باید بدونیم که هر کدام از این روش‌ها با هدف خاصی در وب سرورها استفاده می‌شوند.

در نسخه ی یک Http فقط از Get,post,headپشتیبانی میشد.

ولی در نسخه ی 1.1 پنج روش جدید هم به آن اضافه شد یعنی trace,delete,put,options,connect

بین این روش ها بیشترین کاربرد را درخواست های get, post دارند که در ادامه در مورد این دو کمی بیشتر صحبت می کنیم.

GET: پیام هایی که تو این روش ارسال میشن فقط شامل یک URL هستند البته تو این پیام‌ها میتوانیم تعدادی پارامتر دلخواه در انتهای URL اضافه کنیم و این پارامتر ها به راحتی در مروگر کاربر مشخص هستند.

POST : در این نوع درخواست ها، پارامترهای دلخواهی که اضافه میکنیم، قابل مشاهده نیستند. چون در این روش به جای اضافه کردن پارامترها در انتهای URL، آن‌ها در درون پیام درخواست شده قرار داده می‌شوند.

البته از قسمت developer tools و قسمت network به راحتی قابل تشخیص است.

وب سرور چیست ؟

به زبان ساده، یک web serverوظیفه ی ارسال محتوای یک وب سایت را به کلاینتی که آن را درخواست کرده دارد.

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

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

کاربرد وب سرور چیست و web serverچگونه کار می کند؟

وب سرور می تواند به سخت افزار یا نرم افزارگفته بشه.

از جنبه سخت افزاری، وب سرور یک رایانه است که نرم افزار وب سرور و فایل های اجزای وب سایت را ذخیره می کند، به عنوان مثال اسناد HTML ، تصاویر، استایل شیت های CSS و فایل های جاوا اسکریپت را می‌توان نام برد.

از جنبه نرم افزاری، یک وب سرور شامل چندین بخش می باشد .

حداقل شامل یک سرور HTTP است که چگونگی دسترسی کاربران به فایل های روی هاست را کنترل می کند.

از جمله وب سرورهای معروف نیز می توان به Apache، Nginx، IIS و LiteSpeed اشاره کرد.

وب سرور استاتیک و داینامیک

یک وب سرور استاتیک شامل یک کامپیوتر به همراه یک سرور HTTP است. که آن را استاتیک می نامیم زیرا سرور، فایل های میزبانی شده را همان گونه که هست به مرورگر شما ارسال می‌کند.

یک وب سرور داینامیک، شامل یک وب سرور استاتیک، به علاوه ی یک نرم افزار اضافی، (اغلب یک سرور برنامه و یک پایگاه داده) است. که آن را پویا می نامیم، زیرا سرور برنامه، فایل های میزبانی شده را قبل از فرستادن آن ها به مرورگر شما، از طریق سرور HTTPبه روز می کند.

تکنولوژی های طراحی وب سرور استاتیک در این آموزش

مایکروسافت ویژوال استودیو

کنسول اپلیکیشن

زبان برنامه نویسی سی شارپ

شروع کار

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

اسم پروژه را به دلخواه وارد کرده و دکمه create را میزنیم.

وب سرور ما یک وب سرور استاتیک بوده و تونایی پردازش فایل های سی شارپ ، asp ، jsp یا php را ندارد فقط توانایی ارسال فایل های استاتیک اعم از html ، htm،css ، js ، jpeg ، jpg ، png ، gif و ... را دارد که آن هم توسط مرورگر پردازش می شود و وب سرور دخالتی ندارد فقط باید به مرورگر یک سری اطلاعات مثل از MIME Type را اعلام نمود.

در طول پروژه ما با ساخت سه کلاس سر و کار داریم که عبارت اند از : program و clientوlistener

در ابتدا از قسمت solution که در سمت راست قرار دارد روی پروژه راست کلیک کرده و یک کلاس جدید به اسم listenerایجاد میکنیم.

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

به این صورت می باشد که دستورات آن به صورت asyncنوشته شده اند و در مقیاس گسترده و یک Enterprise App تاثیر خودش را نشان میدهد.

دو فیلد می سازیم یکی برای TcpListener و دیگری برای port

با نوشتن کلمه ctor و زدن دو بار کلید tab سازنده ی کلاس برای ما ساخته می شود به عنوان ورودی متد یک پارامتر را در نظر میگیرم که پورت اجرایی برنامه ما می باشد.

کلاس Tcplistener منتظر درخواست های Tcp می ماند.

در سازنده ی کلاس listener یک شی جدید از tcpListener می سازیم و داخل فیلد میریزیم.

سازنده ی کلاس tcpListener دو مقدار به عنوان ورودی دریافت میکند یکی آی پی های مجاز و دیگری پورت برنامه
ما در اینا انواع آی پی را باز گذاشتیم با نوشتن IpAddress.Any و فیلد پورت را که مقدار دهی کرده ایم به tcpListener می دهیم.

برای شروع کار این کلاس متدی وجود دارد به اسم Start() که باید بعد زا نمونه سازی آن را فراخوانی کرد . این متد به صورت را به صورت زیر مینویسم :

_tcpListener.Start()

برای اینکه برنامه ما MultiUserباشد باید یک متد بسازیم و در پس زمینه آن را اجرا کنیم.

در کلاس listener یک متد async با خروجی void در نظر میگیرم.

درون آن یک حلقه بی نهایت میزنیم به این صورت while(true) تا همیشه برنامه ی ما زنده باشد.

متغیری تعریف میکنیم به اسم دلخواه و در آن _tcpListener را مینویسیم و از آن متد AcceptSocketAsync را فراخوانی میکنیم.

کار این متد به این صورت هست که connection هایی که اصطلاحا pending می باشند را قبول میکند تا برنامه mutltiuser باشد.

حالا اگر این socket ما null بود باید بگوییم از حلقه خارج شود . بایک if و یک break; کار را انجام میدهیم.

ولی اگر null نبود باید یک client handler بسازیم تا مدیریت این task را بپذیرد.

و در نهایت یک task میسازیم تا کارهای مربوط به این thread را انجام دهد.

بحث client handler و کلاس client را پیش میبریم.

از قسمت solution روی پروژه راست کلیک کرده و و یک کلاس جدید به اسم client ایجاد میکنیم.

ما به چند فیلد private نیاز داریم تا ادامه ی کار را انجام دهیم . یکی مربوط به networkstream یکی memoryStream یکی StreamReader و در نهایت یک فیلد ثابت استرینگ برای نمایش نام سرور در ادامه به توضیح هر یک میپردازیم.

با نوشتن سازنده ی کلاس client و قرار دادن پارامتر socket در ادامه networkStream را نمونه سازی میکنیم با همین سوکتی که پاس دادیم سپس فیلد streamReader را نمونه سازی میکنیم و مقدار memorystream را به عنوان Stream پاس میدهیم.

این مطلب را باید بدانیم که هر فایلی که به سمت مرورگر ارسال می شود شامل یک سری اطلاعات مثل Content Type و Content Length و Http Version و Http Method و ... می باشد.

در اینجا برای به دست آوردن content type نیاز به ساخت یک متد داریم که string به ما میدهد در اینجا من از registry ویندوز استفاده کردم.

با توجه به شکل 5646546 اگر به آدرس Computer\HKEY_CLASSES_ROOT\ برویم تمامی فایل های پشتیبانی شده توسط ویندوزقابل رویت می باشد

اگر روی هر کدام کلیک کنیم به عنوان مثال .html از قسمت content type میتوان mime type فایل موردنظر را فهمید به عنوان مثال برای html این عبارت text/html می باما از یک if و یک regular expression استفاده کردیم تا فقط mime هایی که حروف انگلیسی و اعداد در آن ها به کار رفته را بررسی کند و اگر null باشد مقدار application/octect-stram را برگرداند.

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

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

متدی تحت عنوان SendFile طراحی میکنیم که آدرس فایل ها را به عنوان ورودی دریافت میکند.

یک بدنه ی try catch قرار میدهیم تا اگر خطایی رخ داد بدنه ی catch اجرا شود.

داخل try بررسی میکنیم آیا فایل در مسیر وجود دارد یا خیر پس یک شرط مینویسیم و اگر وجود نداشت صفحه ی 404 را طراحی میکنیم .

همانظور که قبلا اشاره شد content-type فایل های html عبارت text/html می باشد و جواب های ok به صورت کد 200 می باشند.

و جواب Not Found با کد 404 مشخص می شود.

از دستور زیر برای ساخت صفحه 404 استفاده میکنیم.

Encoding.ASCII.GetBytes("<html><body><h1>404 File Not Found</h1></body></html>");

Content-type و status-code را نیز تعیین میکنیم.

حال اگر صفحه وجود داشت باید تمام بایت های آن فایل مورد نظر خوانده شود برای این کاراز دستور File.ReadAllBytes(path) استفاده میکنیم و مقدار آن را در یک متغیر میریزیم. از متدی که قبلا نوشتیم هم برای به دست آوردن content-type استفاده میکنیم.

یک متغیر از جنس string و با نام header تعریف میکنیم و مقادیری مثل content-length و content-type و status-code و http method و http version و keep-alive و servername که مرورگر به آنها نیاز دارد را تعیین میکنیم.

به وسیله ی netwrokStream و متد WriteAsync مقادیر header و data را مینویسم و در نهایت flush میکنیم و networkStream را dispose میکنیم توجه کنید که این برنامه به صورت Keep-Alive Close نوشته شده است و ما نیاز به networkStream نداریم پس بهتر است آن را از Ram خارج کنیم.

در ادامه به نوشتن یک متد میپردازیم که وظیفه آن به دست آوردن آدرس صحیح درخواستی کاربر و پاس دادن آن به SendFile می باشد.

چون ممکن است در آن واحد تعداد درخواست های زیادی به سمت سرور برای یک url بیاید از while بی نهایت استفاده میکنیم

به وسیله ی متد seek در memorystream جستجو میکنیم از خانه ی صفر تا Seekorigin.Begin

چون memoryStream را به streamReader پاس داده بودیم متغیری تغریف میکنیم و از متد readline برای خواندن streamreader استفاده میکنیم

خطی که میخوانیم چیزی شبیه به این عبارت است : "GET /index.html HTTP/1.1"
بررسی میکنیم درخواست مورد نظر از نوع Get باشد در غیر این صورت از حلقه خارج شود سپس با استفاده از split() با جدا کننده ی space آدرس فایل را به دست می آوریم .

خانه ی صفرم در عبارت بالا به این صورت است : “Get ”

پس ما به خانه ی یکم نیاز داریم از split با جداکننده ی ? ا استفاده کردیم تا params را حذف کنیم.

و در نهایت آدرس فایل را پاس دادیم.

نکته : فایل های ما در فولدر root قرار گرفته اند.

وقت آن رسیده متد do را بنویسیم من اینجا خواستم اطلاعات به صورت buffer و تکه تکه پردازش شود پس از یک byte[] استفاده کردم و مقدار 4096 را دادم.

یک حلقه ی بی نهایت برای پردازش در نظر گرفتم و از networkstram ، متد read را صدا زدم و تمام و کمال فایل را خواندم.

در نهایت buffer و byteread را بر روی memorystream رایت کردم و متد ProcessHeader را صدا زدم.

خوب باید برگردیم به فایل Listener و یک شیء جدید از client ایجاد کنیم ودر داخل یک Task متد Client.Do را فراخوانی کنیم.

در مرحله پایانی هستیم ، وارد فایل program.cs می شویم و فیلد زیر را میسازیم:

private static Listener _listener;

در بدنه ی Main یک شی جدید از آن ایجاد میکنیم و پورت مورد نظر مثل 80 ، 8080 یا 9090 را پاس میدهیم.

برنامه را Run میکنیم ولی چیزی برای نمایش وجود ندارد چون در داخل فایل root فایلی قرار ندادیم
یک فایل html میسازیم و در روت پروژه قرار میدهیم سپس دوباره برنامه را ران میکنیم.

امیدوارم این مطلب مفید بوده باشد.

فیلم آموزشی در آپارات: https://www.aparat.com/v/bjMJE

منبع بررسی کلاس ها و متد ها

https://docs.microsoft.com/

دانشگاه صدراموسسه صدرالمتالهینمهندسی اینترنت
شاید از این پست‌ها خوشتان بیاید