<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های برنامه نویسی و مفاهیم رایانه</title>
        <link>https://virgool.io/feed/@pythonic</link>
        <description>برنامه نویس پایتون و دوستدار سیستم های توزیع شده، دانش داده ها و زبان عبری http://learnhebrew.ir</description>
        <language>fa</language>
        <pubDate>2026-06-30 19:17:55</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/43533/avatar/7RHmil.jpeg?height=120&amp;width=120</url>
            <title>برنامه نویسی و مفاهیم رایانه</title>
            <link>https://virgool.io/@pythonic</link>
        </image>

                    <item>
                <title>آمار بازدید پست‌های من در سال ۹۹</title>
                <link>https://virgool.io/@pythonic/%D8%A2%D9%85%D8%A7%D8%B1-%D8%A8%D8%A7%D8%B2%D8%AF%DB%8C%D8%AF-%D9%BE%D8%B3%D8%AA-%D9%87%D8%A7%DB%8C-%D9%85%D9%86-%D8%AF%D8%B1-%D8%B3%D8%A7%D9%84-%DB%B9%DB%B9-zyruq0ubxzds</link>
                <description>در طول تاریخ از اعداد استفاده کردیم تا اغلب داد و ستد کنیم و آن‌چیزی که شمردنی است را بشماریم. برای هر عدد واحد درست کردیم تا عددهای زندگی قاطی نشوند و از اعداد، شفاف‌تر استفاده کنیم؛ مثلا وقتی می‌گوییم ده هزار تومان به پول اشاره داریم و وقتی می‌گوییم ده هزار بلیط به بلیط!روز به روز که در زندگی جلو‌تر رفتیم عددها فرقی نکردند ولی این واحدها بودند که زیاد شدند. واحد کریپتو، واحد اصله درخت، واحد فاصله و …«واحد» یک توافق عمومی است برای شمردن؛ تا همانطور که گفتم شمردن‌ها قاطی نشود. مشاهده افراد دارای ثروت (اجتماعی یا مالی) به من ثابت کرده اینکه چه چیزی را بشماریم از اینکه چطور بشماریم مهم‌تر است. هرکس با واحد خاصی مسائل زندگی را می‌شمارد. اینطور به نظرم آمده که مشخص کردن واحد یعنی مشخص کردن اینکه من در زندگی برای چه چیزهایی ارزش قائلم و می‌خواهم چه چیزهایی را در زندگی بشمارم. https://cdn.virgool.io/annual-report/1399/q3hwadadaqxp-GxROs.mp4 اعدادی که بدون واحد ثبت کردمبه ویدیویی که ویرگول برایم ساخته که نگاه می‌کنم میبینم که در سال ۹۹، من در مجموع ۱۰,۴۰۴ کلمه در ویرگول نوشتم و منتشر کردم و مخاطبین، پست‌های من را ۱۷۲ مرتبه پسندیدند و  ۲۵ بار هم نظر خود را روی پست‌های من به اشتراک گذاشتند. در سال ۹۹، ۵۶ نفر در ویرگول من را دنبال کردند تا پست‌های بعدیم را بخوانند. این اعداد نشان میدهند من کاری کرده‌ام. هرکدام به واحدی وصل هستند. از خودم می‌پرسم من کدام واحد را شمارش کرده‌ام؟ کدامیک از واحدهای بالا از همه برای من مهم‌تر است؟ ادامه ویدیو را می‌بینم.آمار از اثر بیرونی می‌گویندطبق آمار پست‌های من ۸,۸۶۳ بار خوانده شدند و ۲,۲۷۸,۸۱۹ ثانیه صرف مطالعه آنها شده است، که با توجه به جمعیتی که در ایران به اینترنت دسترسی دارند، ویرگول به من می‌گوید که توانستم  ۰/۰۳۱۲۴۲۳۷۷ ثانیه، سرانه مطالعه دیجیتال کشور را بالا ببرم.از طرف دیگر ویرگول به من می‌گوید که اگر قرار بود پست‌هایم را چاپ و به دست تک تک خوانندگان برسانم باید ۴۳,۴۶۹ کاغذ مصرف می‌کردم.آن عددهای کوچک ابتدای ویدیو حالا تبدیل شده‌اند به عددهای بزرگ به اینکه من جلوی مصرف این تعداد کاغذ را گرفتم یا به اینکه من  ۰/۰۳۱۲۴۲۳۷۷ ثانیه، سرانه مطالعه دیجیتال کشور را جابه جا کرده‌ام. واحد این عددها برای من ملموس‌تر است.واحد نوشتن چیست؟همه عددهای بالا و همینطور اثر بیرونی که روی خوانندگان و همینطور در مقیاس بزرگتر طبیعت و جامعه اطرافم گذاشتم اعدادی هستند که من دوستشان دارم و به آنها افتخار می‌کنم. اگر چنین ویدیویی دست شما نیز رسید به شما بابت تک تک اعداد تبریک می‌گویم.اثر هر نوشته تا حدودی معلوم است، اگر بنویسید جلوی قطع درخت را می‌گیرید، به سرانه مطالعه کشور اضافه می‌کنید و خوانندگانی جذب می‌کنید که شما را از طریق نوشته‌هایتان می‌شناسند و …به نظرم می‌رسد که نوشته‌های من و شما واحد ندارند ولی اثر بیرونی دارند.</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 24 Mar 2021 17:09:08 +0430</pubDate>
            </item>
                    <item>
                <title>وب سایتی برای پردازش توزیع شده</title>
                <link>https://virgool.io/@pythonic/%D9%88%D8%A8-%D8%B3%D8%A7%DB%8C%D8%AA%DB%8C-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%BE%D8%B1%D8%AF%D8%A7%D8%B2%D8%B4-%D8%AA%D9%88%D8%B2%DB%8C%D8%B9-%D8%B4%D8%AF%D9%87-loisqvqbecpx</link>
                <description>پردازش توزيع شده یا عبارت شناعته شده تر و ملموس تر &quot;سیستم توزیع شده&quot; امروه بخشی از زندگی من و شما و همه مردم جهان است و هر روز با آن سر و کار داریم. یک سیستم توزیع شده، مجموعه ای از موجودات ها یا واحدها محاسباتی است که درون یک شبه به یکدیگر متصل شده اند و همگی در همکاری با هم به دوبال حل یک مسئله واحد هستند&quot;.بنابراین یک سیستم توزیع شده به زبان ساده مجموعه ای از پردازنده ها، حافظه های اصلی و سیستم فایل توزیع شده (مانند NFS در یونیکس، DFS در ويندوز یا HDFS در هدوپ) است که همگی با هم یک منبع پردازشی بسیار بزر را  ورآهم می کنند که برای محاسبات سنگین مانند نمونه موارد زیر به کار می رود.پردازش داده های حجیم موسوم به Big Dataپردازش های لازم برای یادگیری ماشین و شبکه های عصبی مانند پردازش تصویر یا پردازش متنبرای پردازش محاسبات ریاضیاتی در زمینه هایی مانند فیزیک و شیمیبرای سرویس هایی همچون دسترس پذیزی بالا، توازن باربرای فراهم یک بستر برای پردازش موازی که پیش از این به طور سنتی در سامانه های چند پردازنده ای یا چند پردازشی انجام می شد.مورد استفاده در سامانه های هوشمند و در ارتباط با IoTدر این سیستم لزوما یک واحد محاسباتی یک سرور قدرتمند نیست بلکه یک موبایل یا یک حسگر کوچک است. شما با ترکیب &quot;اینترنت + زبان برنامه نویسی + مدل های یادگیری ماشین + سخت افزار راسپری پای&quot; می توانید یک سیستم توزیع شده  هوشمند بسازید.برای نمونه می خواهم جنگل داری هوشمند داشته باشیم پس با داشتن &quot;حسگر + شبکه های سلولی + زبان برنامه نویسی&quot; می توانیم یک شبکه توزیع شده داشته باشیم که این حسگرها محیط را حس می کنند و سپس احتمالا این حسگرها گروه بندی شده اند و با یکدیگر اصطلاحا حرف می زنند و در نهایت بر اساس نیاز داده های خود یا داده های گروه را که پردازش و پالایش شده است را به یک ایستگاه مرکزی می فرستند.اگر بخواهیم هوشمند سازی نجام دهیم، شاید این حسگرها که در یک شبکه به یکدیگر و به ایستگاه وصل هستند، پس از حس یک خطر مانند آتش سوزی و قطعا به صورت بلادرنگ (Real Time) یک فرمان به یک پرنده هوشمند آپاش می فرستند و پرنده را به سوی محل نزدیک خودش که آتش سوزی رخ داده هدایت می کند.بزرگترین سیستم توزیع شده شبکه جهانی اینترنت است که مجموعه ای از مسیریاب ها و سرورهایی است که به یکدیگر متصل شده اند و ما نمی دانیم درخواست ما در کجای این جهان پردازش می شود. سرویس دیگر، پایگاه داده های توزیع شده هستند که مجموعه ای از کلاسترهایی هستند که در نقاط مختلف شهر،کشور، میان کشورها و قاره ها پخش شده اند و سرویس را همواره در دسترس شما قرار می دهند.سیستم های توزیع شده پایه و اساس پردازش و تضمين ارائه سرویس ها هستند. بدون یک سیستم توزیع شده دانشگاه یا موسسه پژوهشی برای انجام پردازش سیگنال های کهشانی برای پی بردن به دیگر زندگانی ها در این گستره کهکشان وابسته به ابررایانه های گران قیمت و حجیم و پر هزینه برای نگهداری هستند.اما با وجود تئوری سیستم های توزیع شده امکان اتصال واحدهای پردازشی بسیار کوچک و ضعیف در سراسر جهان به هم است تا یک واحد پردازشی بزرگ فراهم شود. نمونه بارز این دسته از فعالیت ها پروژه ای موسوم به SETI@Home است که از منابع پردازشی رایانه های شخصی خانگی در زمان بی کاری آنها برای پردازش موازی استفاده می کند.به هر رو یک كاردان (فوق دیپلم) تا یک دکتری نمی تواند از مفاهيم سیستم توزیع شده فرار کند. اگر شما دانش آموخته خوش مصنوعی هستید نیاز به منابع پردازشی بالا دارید. قطعا مترجم گوگل این حجم از درخواست های ورودی با سختی پردازش را نمی تواند با یک یا چندین سیستم متصل به هم پردازش کند.سیستم های توزیع شده به صورت جغرافیایی پخش هستند که این بدین معنی است که درخواست شما به نزدیکترین محل به شما می تواند فرستاده شود که به معنی کاهش تعداد مسیریاب ها است. به هر رو، فراگیری سیستم توزیع شده بسیار اهمیت دارد و من تلاش دارم با توکل به خدا در وب سایت زیر از پایه آغاز به آموزش مفاهیم کنم.http://distributedcomputing.irhttps://t.me/distributedcomputing_irالبته آموزش از پایه است و راه طولانی و امیدوارم به خدا که توانایی دانش، زمانی و انگیزه ای برای من باشد تا بتوانم این فيلد را آموزش دهم چون بسیار پر اهمیت است. زبان هایی که نیز به کار خواهم برد و آموزش می دهم، زبان Erlang و Python (برای موارد کاربردی و ویژه) هستند.شاد و پیروز و تندرست و بی نیاز باشید.</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Mon, 22 Mar 2021 23:15:16 +0430</pubDate>
            </item>
                    <item>
                <title>مفهوم args* و kwargs** در پایتون</title>
                <link>https://virgool.io/@pythonic/%D9%85%D9%81%D9%87%D9%88%D9%85-args-%D9%88-kwargs-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-lrrigpbcgtx0</link>
                <description>در زبان های برنامه نویسی، هر تابع می تواند هیچ، یک یا چندین آرگومان ورودی دریافت کند. در صورتی که هیچ یک از این آرگومان ها دارای مقدار پیش فرض نباشند، پس در زمان فراخوانی باید به ازای هر کدام و به ترتیب از چپ به راست، یک مقدار وارد کنیم.فرض کنید می خواهید عملیاتی ریاضی بر روی n عدد انجام دهید. برای حل این مسئله n تعداد آرگومان های تابع است که قاعدتا n&gt;=2 است. اکنون که طرح مسئله را می دانیم، باید متوجه شده باشیم که n در زمان تعریف تابع آشکار نیست و می تواند بر اساس فراخوانی های بعدی، متغیر باشد.کد شماره ۱در کد بالا (۱) تابعی با سه آرگومان نوشته شده است که مقدار جمع سه عدد ارسالی به آن را برگشت می دهد. در زمان فراخوانی سه پارامتر را به آن ارسال کرده ایم. حال فرض کنید اگر به جای سه پارامتر، دو یا چهار پارامتر ارسال کنیم. در این حالت خطایی مانند خروجی زیر (۱) رخ می دهد.خروجی ۱عبارت args*در تعریف آرگومان های یک تابع، زمانی که پیش از نام آرگومان یک * قرار گیرد، آن متغیر به گونه چندین ورودی پی در پی خواهد بود که برابر با یک تاپل (Tuple) از ورودی ها تفسیر می شود. پارامترهای ورودی مانند فهرست 3 ,2 ,1 ترتیب ورودی ها هستند.*args = 1, 2, 3زمانی که می خواهیم که تاپل را تعریف کنیم دو شیوه زیر در پایتون وجود دارد. هر دو کد زیر یک تاپل از اعداد صحیح می سازند.t1 = (1, 2, 3)
t2 = 1, 2, 3البته توجه کنید که قطعا آرگومان های ورودی که با args* فرستاده می شوند، لزوما از یک نوع نیستند. در کد زیر من به جای واژه شناخته شده args*، واژه my_args* را به جای فهرست تاپل آرگومان های ورودی تعیین کرده ام.کد شماره ۲در خط دوم کد بالا (۲)، تابع و به کمک تابع درونی ()type نوع my_args* را قاعدتا کلاس تاپل برگشت می دهد. در این مثال ترتیب ورودی ها رشته، اعشاری، صحیح و بولی هستند که شما می توانید تعداد بیشتر یا کمتر و ترتیب نوع های دیگر یا همگی از یک نوع را ارسال کنید.در کد زیر (۳)، تابع بالا بازنویسی شده است، به گونه ای که دو آرگومان arg1 و arg2 احباری هستند ولی my_args* اختیاری است زیرا که آن می تواند تاپلی از هیچ، یک یا چندین ورودی باشد. پس در شکل زیر می بینید که یک بار با ۶ ورودی فراخوانی کرده ام که دو تای اول مربوط به arg1 و arg2 و چهار تای آخر مربوط به my_args* هستند.func(&#039;aa&#039;, 10.2, &#039;b&#039;, 12, True, &#039;h&#039;)
func(&#039;aa&#039;, 10.2)کد شماره ۳در کد زیر (۴)، تابعی نوشته ایم که دو آروگومان اجباری arg1 و arg2 تعریف شده است. در ادامه یک تاپل به نام parameters با دو مقدار رشته ای و عدد صحیح تعریف شده است که سپس نام متغیر را به صورت parameters* به تابع فرستاده ایم.کد شماره ۴کد بالا نشان می دهد که می توانیم به تعداد، ترتیب و نوع ورودی های یک تابع، یک تاپل بسازیم و سپس با استفاده از عبارت args* که آغاز آن یک * است، نام متغیر تاپل را به تابع بفرستیم. برای نمونه فرض کنید می خواهیم به پایگاه داده وصل شویم که نام تابع اتصال ()db_connect که ورودی های زیر را نیاز دارد.username = &#039;amirnami&#039;
password = &#039;1234&#039;
hostname = &#039;localhost&#039;
port = 3306اکنون می توانیم به جای تعریف خط به خط متغیرهای بالا یک تاپل با ترتیب ورودی های تابع بسازیم و سپس آن را به تابع یک جا ارسال کنیم. توجه کنید در زمان تعریف تاپل (در اینجا connection_parameters) نیازی به استفاده از پرانتزها نیست و به عبارتی اگر جلوی نام متغیر و با استفاده از ویرگول و بدون پرانتز، مقدارهایی را به متغیر بدهیم، آن متغیر از نوع تاپل خواهد بود.connection_parameters = &#039;amirnami&#039;, &#039;1234&#039;, &#039;localhost&#039;, 3306
db_connect(*connection_parameters)عبارت kwargs**دو عبارت args* و kwargs** دقیقا دو کاربرد یکسان دارند ولی زمانی که بخواهیم ورودی ها را به صورت تاپل ارسال کنیم از args* و زمانی که بخواهیم به صورت دوتایی های Key:Value ارسال کنیم از kwargs** استفاده کنیم.در کد زیر (۵) یک تابع با متغیر user** تعریف شده است، پس این تابع دوتایی های Key=Value را دریافت می کند. درون تابع نخست نوع متغیر user نشان داده می شود که از نوع کلاس دیکشنری است. سپس سه ورودی fname و lname و age با مقدارشان به تابع فرستاده شده اند.کد شماره ۵در کد زیر (۶) آشکارا ورودی را از نوع دیکشنری را به تابع ()func فرستاده ایم. توجه کنید که دو دیکشنری user1 و user2 تعداد دوتایی های یکسان ندارند (کلید from در user2). سپس این دو متغیر را به صورت user1** و user2** به تابع ()func فرستاده ایم، که ورودی user** را دارد.کد شماره ۶در کد زیر که اینجا برداشته شده است، می خواهیم یک URL در SqlAchemy که برابر با همان Connection String در سی شاپ است را توسط کلاس URL بسازیم. برای این کار، دیکشنری از دوتایی های لازم برای اتصال تعریف کرده ایم که تحت نام parameters است. سپس متغیر را به صورت parameters** به متد سازنده کلاس URL فرستاده ایم.from sqlalchemy.engine.url import URL
from sqlalchemy.exc import DatabaseError
parameters = {
    &#039;drivername&#039; : &#039;mysql+mysqlconnector&#039;,
    &#039;username&#039;: &#039;root&#039;,
    &#039;password&#039;: &#039;123&#039;,
    &#039;host&#039;: &#039;localhost&#039;,
    &#039;port&#039;: 3306,
    &#039;database&#039; : &#039;employees&#039;
}
mysql_url = URL(**parameters)
engine2 = create_engine(mysql_url)</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 11 Dec 2020 13:44:29 +0330</pubDate>
            </item>
                    <item>
                <title>تکرار شونده یا Iterator در پایتون</title>
                <link>https://virgool.io/@pythonic/%D8%AA%DA%A9%D8%B1%D8%A7%D8%B1-%D8%B4%D9%88%D9%86%D8%AF%D9%87-%DB%8C%D8%A7-iterator-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-lg7yhsfw79b4</link>
                <description>در پایتون تعدادی نوع داده (Data Type) مانند تاپل و لیست هستند که توالی از عناصر هستند و می توانیم با استفاده از حلقه for..in آن را پیمایش کنیم و هر یک از عنصرهای آن را نمایش دهیم. هر لیست یا تاپل می تواند صفر یا چندین آیتم از نوع های دیگر داشته باشد.تکرارشونده یا Iteratorدر اینجا با یک مثال ساده تکرار شونده ها را خواهم گفت. تکرار شونده ها اشیایی هستند که می توانند بارها و بارها فراخوانی شوند و هر بار مقداری را تولید کنند. در حلقه for..in اگر متغیر یا عبارتی که پس از واژه کلیدی in می آید یک iterator نباشد، پایتون تلاش می کند که آن را به یک iterator تبدیل کند.تابع ()nextتابع ()next یکی از توابع درونی پایتون است که به عنوان ورودی یک Iterator را دریافت می کند و در هر بار فراخوانی از نخستین عنصر تا آخرین عنصر را برگشت می دهد. در شکل زیر یک تاپل به نام t تعریف کرده ایم و سپس می خواهیم اولین عنصر آن را با ()next نمایش دهیم ولی خطایی نشان می دهد مبنی بر اینکه t (تاپل) یک Iterator نیست، پس نمی توانیم t را با ()next استفاده کنیم.t = 1, 2, 3, 4
print(next(t))تابع ()iterتابع ()iter نیز یکی دیگر از توابع درونی پایتون است که همانند ()next در ارتباط با تکرار شونده ها است. این تابع به عنوان ورودی لیست، تاپل یا رشته (توالی از کاراکترها) را دریافت می کند و سپس آن را به یک Iterator تبدیل می کند و از این می تواند توسط تابع ()next استفاده شوند.t = 1, 2, 3, 4
print(next(t))
t_i = iter(t)
print(type(t_i))خود اعداد هرگز نمی توانند به Iterator تبدیل شوند.تابع ()rangeتابع ()range برای ایجاد یک لیست عددی در بازه ای مشخص میان [a, b-1] استفاده می شود. برای نمونه اگر a=1 و  b=11 یا (11, 1)range باشد، پس لیستی از اعداد ۱ تا ۱۰ (b-1) ساخته خواهد شد. اگر تنها مقدار 10 (تک مقدار) یا (10)range باشد، لیستی از صفر تا ۹ ساخته می شود.بی توجه به این که ()range چه کاربردی دارد، می خواهم بگویم که این تابع یک Iterator تولید نمی کند. در کد زیر نخست خروجی ()range در متغیر l ریخته شده است که از نوع list خواهد بود که با توجه به نوشته های بالا یک Iterator نیست.در کد زیر لیست l را به کمک تابع ()iter به تکرار شونده l_i تبدیل کرده ایم و سپس به کمک یک حلقه for ساده آیتم های درون آن را نمایش داده ایم.در پایتون گونه ای از توابع به نام Generator ها هستند که مقدار محاسبه شده را به جای برگشت (return) و دخیره سازی در حافظه، در زمان نیاز (به هنگام استفاده) را به صورت یک Iterator برگشت می دهند. برای آشنایی با این مفهوم لینک زیر را بخوانید. https://virgool.io/@pythonic/%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-generator-%D9%88-%DA%A9%D9%84%D9%85%D9%87-%DA%A9%D9%84%DB%8C%D8%AF%DB%8C-yield-rl8m1egndvav </description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 09 Dec 2020 14:51:26 +0330</pubDate>
            </item>
                    <item>
                <title>برنامه نویسی همگام و ناهمگام چیست</title>
                <link>https://virgool.io/coderlife/%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D9%87%D9%85%DA%AF%D8%A7%D9%85-%D9%88-%D9%86%D8%A7%D9%87%D9%85%DA%AF%D8%A7%D9%85-%DA%86%DB%8C%D8%B3%D8%AA-ajemhajjtvp4</link>
                <description>برنامه های نرم افزاری به دو دسته بلاک شدنی (Blocking Programming) هستند به طوری که با اجرا شدن یک واحد از برنامه، کل بخش های دیگر باید منتظر بمانند تا اجرای واحد قبلی به اتمام برسد. فرض کنید برنامه شما (مانند Office Word) چندین پردازش (فرایند) دارد.در این حالت، با اجرا شدن یک فرایند، مابقی فرایندهای آن برنامه باید منتظر بمانند تا اجرای فرایند قبلی به پایان برسد. یکی از عواملی که باعث می شود اجرای یک فرایند زمان بر باشد، عملیات I/O است که می تواند از روی دیسک یا شبکه باشد.آنچه که گفته شد را برنامه های بلاک شدنی یا همگام (Synchronous Programming) می گویند جایی که اجرای یک فرایند، اجرای دیگر فرایندها را به تعویق می اندازد. در برابر این شیوه، برنامه نویسی بلاک نشدنی (Nonblocking Programming) یا برنامه نویسی ناهمگام (Asynchronous Programming) وجود دارد.در برنامه نویسی ناهمگام، اجرای یک فرایند منوط به پایان یافتن یک فرایند دیگر نیست، بلکه اگر فرایندی نیاز به عملیات I/O داشته باشد، در پس زمینه اجرا شده و سپس فرایند دیگر اجرا می شود و پس از آنکه عملیات I/O به پایان رسید، فرایند از پایان یافتن خود آگاه سازی می کند. https://virgool.io/@pythonic/توابع-generator-و-کلمه-کلیدی-yield-rl8m1egndvav مزیت برنامه نویسی همگاممزیت اصلی برنامه نویسی ناهمگام برای بهبود کارایی (Performance) است جایی که نمی خواهیم کل عملکرد برنامه به خاطر یک فرایند سنگین مانند عملیات I/O متوقف شود. برنامه نویسی ناهمگام به گونه ای است که یک فرایند (نخ - Thread) از یک برنامه در پس زمینه اجرا می شود و پس از به اتمام رسیدن، نخ اصلی را از به پایان رسیدن خودش آگاه می کند.توجه کنید در حین اجرای نخی که نیاز به I/O دارد، نخی دیگر شروع به اجرا شدن می کند و در همین حین فرایند (نخ) پس زمینه نیز اجرا می شود (مثلا خواندن از وب یا پایگاه داده یا یک فایل متنی روی دیسک)، سپس  پاسخ را اطلاع می دهد.کاربردی ساده از برنامه نویسی ناهمگامفرض کنید در برنامه تان می خواهید تعدادی سطر را از پایگاه داده بخوانید. برای این منظور یک اتصال درون برنامه ایجاد کرده و سپس کوئری مورد نظر را از طریق واسط برنامه نویسی پایگاه داده و از درون برنامه ارسال می کنید.آیا بخش های دیگر برنامه می توانند منتظر بدست آوردن سطرهای مربوط به پاسخ کوئری باشند؟ قاعدتا پاسخ خیر است. در اینجا می توانید توابع خواندن از پایگاه داده را به صورت ناهمگام (async) اجرا کنید زیرا که بدست آوردن (SELECTّ) از پایگاه داده یک عملیات I/O است.همه آنچه که می خواهیم بگوییم در شکل زیر نشان داده شده است. چرا باید به خاطر بخش آبی رنگ که دریافت سطرهای جدول از پایگاه داده است، بخش قرمز رنگ، یعنی دیگر بخش های برنامه متوقف شوند که به عبارتی به معنی متوقف شدن کل عملکرد برنامه است.https://fsprojects.github.io/SQLProvider/core/async.htmlبه طور کلی در رایانه دو عملیات CPU-Bound و I/O-Bound وجود دارد. عملیات های CPU-Bound بسیار وابسته داشتن پردازنده هستند. در برابر این، عملیات های I/O نیازی به پردازنده ندارند و در مقابل برای اتمام خود، باید خواندن یا نوشتن را انجام دهند.زمانی که پردازنده نیاز به خواندن یا نوشتن دارد، از حالت اجرا خارج شده و از این رو پردازنده از آن باز پس گرفته می شود. در این زمان فرایند به حالت معلق (Suspend) می رود و تا زمانی که عملیات خواندن یا نوشتن به پایان نرسد، پردازنده را نخواهد گرفت و از این رو CPU را نخواهد داشت.اکنون شما همین را درون یک پردازش (فرایند) در نظر بگیرید. اگر حتی فرایند چند نخی (Multithreading) باشد، یا اینکه برنامه به صورت چند پردازشی (Multiprocessing) باشد، اگر یک نخ یا فرایند از برنامه عملیات I/O انجام شود، کل آن برنامه معلق می شود. در سیستم عامل ها، زمان معلق شدن برنامه شما می بینید که مکان نما (Cursor) تغییر می کند. بنابراین در چنین مواردی نیاز است تا برنامه نویسی ناهمگام را استفاده کنیم.</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Tue, 08 Dec 2020 17:42:35 +0330</pubDate>
            </item>
                    <item>
                <title>توابع Generator و کلمه کلیدی yield</title>
                <link>https://virgool.io/@pythonic/%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-generator-%D9%88-%DA%A9%D9%84%D9%85%D9%87-%DA%A9%D9%84%DB%8C%D8%AF%DB%8C-yield-rl8m1egndvav</link>
                <description>https://www.educba.com/python-yield/مفهوم تابع در زبان های برنامه نویسی از مفهوم توابع ریاضی گرفته شده است که در ساده ترین حالت یک ورودی و یک خروجی دارد. y=ax+b تابعی است که x ورودی آن و y خروجی آن و a و b ضرایب (پارامترهای) تابع هستند.تابع های برنامه نویسی می توانند هیچ، یک یا چندین ورودی داشته باشند و هیچ یا چندین خروجی داشته باشند. زمانی که یک تابع چیزی را برگشت دهد، این مقدار توسط عبارت return برگشت داده می شود. به عبارت دیگر درون بدنه تابع، محاسبات انجام می شود و سپس مقدار برگشت داده می شود.فرض کنید می خواهید یک فایل بزرگ را بخوانید چه چیزی برای انجام چنین چیزی لازم است؟ بدون قطع حافظه اصلی یا RAM مهمترین چیز است زیرا فایل حجیم با تعداد بسیاری از خطوط، باید درون حافظه اصلی بارگذاری شود، پس احتمالا با کمبود حافظه مواجه خواهید شد.MemoryErrorتابع های Generatorدر زبان پایتون یک تابع Generator، تابعی است که به جای برگشت دادن مقداری با عبارت return، از عبارت yield استفاده می کند بدین گونه که به جای برگشت دادن مقدار توسط return، برگشت دادن مقدار را به تاخیر می اندازد تا زمانی که تابع را استفاده (فراخوانی) کنیم. به عبارت دیگر استفاده به هنگام نیاز (فراخوانی)، هدف Generator ها است.در Generator ها عبارت return وجود ندارد.در کد زیر یک تابع معمولی برای بدست آوردن اعداد زوج میان صفر تا ۱۰۰۰۰ نمایش داده شده است. توجه کنید در اینجا نتیجه تابع در حافظه نگهداری می شود. بنابراین اگر تعداد محاسبات از ۱۰۰۰۰ تا ۱۰۰۰۰۰۰۰۰۰ افزایش پیدا کند، پس احتمالا سیستم با کمبود حافظه و از کار افتادن برنامه یا حتی سیستم عامل دچار خواهد شد.کد شماره ۱در کد بالا (۱) به محض اجرای تابع ()print مقدار برگشتی از تابع نمایش داده می شود. در کد زیر یک Generator را نوشته ایم. توجه کنید تابعی Generator است که درون آن یک یا چندین عبارت yield باشد و از این رو عبارت yield بیرون از یک تابع بی معنی است.کد شماره ۲تفاوت اصلی yield یا توابع Generator در این است که مقدار برگشتی یا مقدار محاسبه یا نتیجه محاسبه در حافظه نگه داشته نمی شود. توجه کنید در کد بالا (۲) پیش از متغیر number عبارت yield آورده شده است. همچنین در این مثال تنها یک عبارت yield پیش از مقدار مد نظر ما آورده شده است.تابع Generator اشیا تکرار پذیر هستنددر شکل ۲، مقدار برگشتی تابع در متغیر output ریخته شده است و در خط بعدی می خواهیم آن را با تابع ()print نمایش دهیم ولی پیامی نشان داده می شود که این شی از نوع generator است. بنابراین باید شی Generator را توسط یکی از سه روش زیر پیمایش کنیم.حلقه for ... inتبدیل به لیستاستفاده از تابع ()next https://virgool.io/@pythonic/%D8%AA%DA%A9%D8%B1%D8%A7%D8%B1-%D8%B4%D9%88%D9%86%D8%AF%D9%87-%DB%8C%D8%A7-iterator-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-lg7yhsfw79b4 استفاده از حلقه for ... inگفته شد که اشیا Generator از نوع تکرارپذیرها (Iterator) هستند و از این رو توسط حلقه تکرار for ... in قابل پیمایش هستند. در کد شکل زیر (۳) می خواهیم روی اشیا درون متغیر output (مربوط به شکل ۲) پیمایش انجام دهیم. بنابراین هر یک از عناصر چاپ شده یک عدد زوج خواهد بود.کد شکل ۳استفاده از لیستگفته شد که اشیا Generator در حافظه اصلی نگهداری نمی شوند، بنابراین در کد شکل زیر که بلافاصله پس از کد شکل ۳ (حلقه for ... in) بالا انجام شده، متغیر output را به کمک تابع ()list به لیست تبدیل کردیم که دیگر این لیست دارای مقدارهای واقعی و غیر شی Generator هستند.کد شکل ۴بنابراین چون اشیا Generator در حافظه نگهداری نمی شوند، پس به گونه ای یک بار مصرف هستند و از این رو در شکل زیر (۵) پس از اجرای کد حلقه شکل ۳، باید (البته تنهای برای تست در این نوشته) یک بار دیگر کد  متغیر output را مانند شکل ۲ فراخوانی کنیم.کد شکل ۵تابع ()next در پایتونتابع ()next یکی از توابع درونی (Built-in) در پایتون است که بر روی تکرارپذیرها (Iterator) کاربرد دارد. ورودی آن یک تکرارپذیر و خروجی آن یک آیتم درون تکرارپذیر است و به همین روند، میتوان با فراخوانی ()next یکی یکی آیتم ها را نشان داد.در کد بالا اولین آیتم توسط اولین تابع ()next نمایش داده شده که اولین عدد زوج یعنی عدد صفر است. به همین ترتیب دیگر آیتم های بعدی با هر بار فراخوانی تابع ()next فراخوانی شدند.خلاصهتابعی که به جای return عبارت yield را به کار برده باشد، یک Generator است که به صورت یک Iterator از اشیا Generator قابل پیمایش است. Generator ها هرگز در حافظه نگهداری نمی شوند و از این رو برای محاسبات سنگین مناسب هستند که نیاز به فضای RAM بالا دارند. یک نمونه از آنها، خواندن یک فایل متنیبزرگ با تعداد بسیاری خط است.همچنین مقدار برگشتی یک تابع Generator تنها یک بار قابل مصرف است و درون یک فایل یا قطعه کد اگر جایی از کد استفاده و پیمایش شد، باید در صورت نیاز برای استفاده در همان کد، یک بار دیگر تابع Generator فراخوانی شود.</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Sun, 06 Dec 2020 20:49:24 +0330</pubDate>
            </item>
                    <item>
                <title>کنترل بر تایپ کردن ورودی در فرم HTML با cleave.js</title>
                <link>https://virgool.io/@pythonic/%DA%A9%D9%86%D8%AA%D8%B1%D9%84-%D8%A8%D8%B1-%D8%AA%D8%A7%DB%8C%D9%BE-%D8%AF%D8%A7%D8%AF%D9%87-%D9%87%D8%A7-%D8%AF%D8%B1-%D9%81%D8%B1%D9%85-html-%D8%A8%D8%A7-cleavejs-a5e9t3tem2u3</link>
                <description>به عنوان یک برنامه نویس وب برای شما پیش آمده تا کنترل کاملی بر روی داده ها در زمان تایپ در فرم HTML داشته باشید. برای نمونه می خواهید ۱۶ رقم کارت اعتباری را دریافت کنید و می خواهید مانند شماره های روی کارت، چهار رقم با فاصله از یکدیگر نوشته شوند.کتابخانه cleave.js به زبان جاوا اسکریپت اجازه می دهد تابتوانید فرمت ورودی به تگ input را در زمان تایپ کردن کنترل کنید. برای نمونه می خواهید تاریخ در زمان تایپ خودکار فرمت 1399.9.14 را ایجاد کند به عبارت دیگر شما دستی نقطه را در جای مشخص وارد نکنید.فایل جاوا اسکریپت یا CDN رابه درون فایل HTML پیوست کند.نیاز به یک فایل js دارید تا کدهای استفاده از کتابخانه cleave.js در آن فراخوانی شوند. (کنترل بر فرم ها)یک فرم HTML شامل تگ های input تعریف کنید.اینجا یک مثال هایی آورده شده اند. برای استفاده از این کتابخانه باید نمونه ای از شی Cleave را بسازید. برای دسترسی به تگ مربوطه، می توانید از نام ID یا Class درون تگ استفاده کنید. در کد زیر می خواهیم فرمت ۱۶ رقمی کارت اعتباری به همراه انتخاب کد کوتاه کشور IR, US, AF مشخص شده اند.var cleave = new Cleave(&#039;.input-element&#039;, {
    creditCard: true,
    phoneRegionCode: &#039;{country}&#039;
});درکد زیر می خواهیم تاریخ مانند 14-09-1399 به صورت خودکار ساخته شود، پس عبارت های date=true و delemiter برابر با &#x27;-&#x27; مقدار دهی شده اند. شما می توانید به جای &#x27;-&#x27; از نقطه برای delimeter استفاده کنید. گزینه dataPattern نیز شامل فرمت Y:m:d است.var cleave = new Cleave(&#039;.input-element&#039;, {
     date: true,
     delimeter = &#039;-&#039;
     dataPattern: [&#039;Y&#039;, &#039;m&#039;, &#039;d&#039;]
});نمونه دیگر در کد زیر آورده شده است.var cleave = new Cleave(&#039;.input-element&#039;, {     
     date: true,
     dataPattern: &#039;[&#039;m&#039;, &#039;y&#039;]&#039;
});در همان لینک بالا نمونه مثال های دیگری آورده شده اند. همچنین میتوانید از لینک های زیر نیز نمونه واقعی و پیاده سازی شده ساده را ببینید.JSFiddle (Basic)JSFiddle (More cases)React JSFiddleAngular JSFiddleو راهنمای کتابخانه</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 04 Dec 2020 21:17:41 +0330</pubDate>
            </item>
                    <item>
                <title>نظارت بر سیستم فایل توسط پایتون و ماژول watchdog</title>
                <link>https://virgool.io/@pythonic/%D9%86%D8%B8%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1-%D8%B3%DB%8C%D8%B3%D8%AA%D9%85-%D9%81%D8%A7%DB%8C%D9%84-%D8%AA%D9%88%D8%B3%D8%B7-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-%D9%88-%D9%85%D8%A7%DA%98%D9%88%D9%84-watchdog-s53wtyblcp9j</link>
                <description>واژه watchdog به معنی &quot;سگ نگهبان&quot; است و از دید یک برنامه رایانه ای، ابزاری است که بر فعالیت های سیستم فایل و تغییرات اعمال شده بر روی آن نظارت دارد و هر تغییری مانند ساخت یک فایل (دایرکتوری)، تغییر نام، پاک شدن یا تغییر محتوا را گزارش می دهد.واسط برنامه نویسی inotify در لینوکسدر لینوکس API ای به نام inotify هست که ابزاری برای زبان سی و سی پلاس پلاس که اجازه می دهد تا یک سیستم فایل را نظارت کنیم. توجه کنید که در لینوکس، یک سیستم فایل توسط یک دایرکتوری برای پیمایش در دسترس است.در واقع پس از سوار کردن سیستم فایلی مانند ext4 یا btrfs یا ntfs بر روی هارد دیسک یا پارتیشن، توسط دستوری به نام mount هست که توسط آن یک دایرکتوری بر روی یک سیستم فایل (هارد دیسک یا پارتیشنی از آن) سوار می شود و از این پس از درون دسکتاپ یا خط فرمان به آن دسترسی خواهیم داشت.ماژول watchdog برای پایتونواسط برنامه نویسی inotify بر پایه زبان سی نوشته شده است و در برنامه های سی و سی پلاس پلاس کاربرد دارد. نسخه پایتونی آن به نام ماژول pyinotify نیز در دسترس است ولی می خواهم در این نوشته ماژول دیگری به نام watchdog را به کار ببرم.# on linux, mac and unix
mkdir watchdog_test
cd watchdog_test
virtualenv env -p python3
source env/bin/activateتوضیح با یک مثال سادهاستفاده از watchdog برای پایتون بسیار ساده است. فرض بر این است که شما می خواهید یک دایرکتوری اشتراکی روی یک سرور را مانیتور کنید که آیا کارمندان شرکت روی آن چیزی که مد نظر شما بوده، مثلا یک فایل پی دی اف از یک گزارش را در ساعتی مشخص ریخته اند یا نه. آیامی توانیم بفهمیم کدام شخص فایل را کپی کرده؟ آیا می توانیم یک لاگ (Log) از تغییرات درون داریرکتوری مورد نظر ثبت کنیم.import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandlerدر کد بالا تعدادی از ماژول های مورد نیاز برنامه ساده مان را پیوست کرده ایم. در ادامه خواهید دید که از sys برای دریافت ورودی از خط فرمان کمک گرفته ایم. در واقع ورودی یک تک رشته است که نام یا مسیری به یک دایرکتوری است.از تابع ()sleep ماژول time برای به خواب بردن و از نو بیدار کردن برنامه یا بهتر است بگوییم ناظر سیستم فایل استفاده می کنیم. در واقع می خواهیم هر n ثاینه یک بار ناظر دایرکتوری مورد نظر را بررسی می کند که آیا تغییری در آن رخ داده است.فایل یا زیر دایرکتوری تازه ساخته شده است.فایل یا زیر دایرکتوری پاک شده است.فایلی یا دایرکتوری انتقال داده شده است.درون فایلی تغییر کرده است.ماژول logging برای ثبت رویدادهای درون یک برنامه مورد استفاده قرار می گیرد. این مورد را در سیستم عامل ها، برنامه ها، پایگاه داده ها و حتی برنامه های وب دیده اید. ماژول هایی که فرایند لاگ را انجام می دهند، دو چیز را نیاز دارند: ۱) چه اطلاعاتی و چه سطحی از اطلاعات لاگ شود و ۲) در کجا لاگ شود.در کدی که در این نوشته مربوط به لاگ کردن است، در واقع لاگ ها بر روی خروجی استاندارد یا همان Standard Output یا به عبارت بهتر خط فرمان سیستم عامل نشان داده می شود. ولی محل خروجی می تواند یک فایل روی دیسک نیز باشد.نظارت بر سیستم فایل مبتنی بر رویداد گرایی استرویداد (Event) چیست؟ به ساده ترین زبان و بی توجه به زمینه برنامه، رویداد چیزی است که رخ می دهد و در برابر آن باید یک پاسخ یا Action انجام شود. در اینجا رویدادها تغییراتی است که درون سیستم فایل یا داریرکتوری (یا فایل) رخ می دهند و ما می خواهیم یک پاسخ به آن بدهیم. این پاسخ یا Action توسط watchdog و کلاس های آن انجام می شود. در بالا چهار تغییر را گفته ام و در ادامه در زیر از نو آنها را بازنویسی خواهم کرد.فایل یا زیر دایرکتوری تازه ساخته شده است. ()on_createdفایل یا زیر دایرکتوری پاک شده است. ()on_removedفایلی یا دایرکتوری انتقال داده شده است. ()on_movedدرون فایلی تغییر کرده است. ()on_modifiedکلاس Observerاین کلاس بخش اصلی watchdog است، جایی که زمانبدی نظارت بر دایرکتوری مربوطه انجام می شود.observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
print(&amp;quotHello&amp;quot) در کد بالا یک نمونه از کلاس Observer ساخته ایم و سپس متد ()schedule را با سه پارامتر فراخوانی می کنیم. فراخوانی نخست متغیری است به نام event_handler که در ادامه نشان می دهم که از نوع کلاس LoggingEventHandler است.در واقع پارامتر اول ()schedule متغیری است که به یکی از کلاس های اداره کننده رویدادها (Event Handler) اشاره می کند. پارامتر دوم مسیر دایرکتوری است که می خواهیم زمانبدی نظارت بر روی آن باشد و توجه کنید نظارت بر رویدادها توسط کلاس های Event Handler انجام می شود (نه Observer).پارامتر سوم recursive=True است که اجازه می دهد تا برگشتی (Recursive) و تو در تو زیر دایرکتوری های درون دایرکتوری ما نیز مورد هدف قرار گیرند. توجه کنید مقدار recursive به صورت پیش فرض برابر با False است و برگشتی بودن نیز غیر فعال است. در نهایت متد ()start از کلاس Observer فراخوانی شده است.event_handler = LoggingEventHandler()در کدها بالا متغیری به نام event_handler از یکی از چندین کلاس اداره کننده رویدادها به نام LoggingEventHandler ساخته می شود. در پایان کد، خط های زیر نوشته شده اند.try:
        while True:
                time.sleep(10)
except KeyboardInterrupt:
        observer.stop()
         print(&amp;quotGoodbye&amp;quot)
observer.join()در یک حلقه while True و تا زمانی که Ctrl+c  (خاتمه دادن به برنامه در خط فرمان) کلیک نشده باشد، پس برنامه هر ۱۰ ثانیه یک بار بررسی می کند که آیا تغییری در دایرکتوری رخ داده است. در صورتی که Ctrl+C کلیک شود، پس استثنای KeyboardInterrupt رخ داده و تابع ()stop از کلاس Observer فراخوانی شده و فرایند نظارت پایان می یابد.توجه کنید که کلاس Observer پیاده سازی نخ ها (Thread) است و دو متد ()stop و ()join مربوط به مفاهیم threading هستند. تابع ()join باعث می شود تا نخی که کدهای ما در آن فراخوانی شده اند به حالت انتظار برود تا زمانی که نخ اصلی thread1 خاتمه پیدا کند.لاگ کردن اطلاعاتدر کد زیر متد ()basicConfig فراخوانی شده تا لاگ کردن در سطح logging و برای نمایش لاگ ها به صورت بر خط و بر روی خط فرمان آماده شوند. بدین معنی که هر بار یک تغییر مانند کپی کردن یا ساخت یک فایل یا دایرکتوری درون دایرکتوری مربوطه، یک مطابق با نوع رویداد نمایش داده می شود.رویداد ()on_createdرویداد ()on_deletedرویداد ()on_movedرویداد ()on_modified logging.basicConfig(level=logging.INFO, format=&#039;%(asctime)s - %(message)s&#039;, datefmt=&#039;%Y-%m-%d %H:%M:%S&#039;) https://coderlife.ir/%D8%B4%DB%8C%D9%88%D9%87-%D9%87%D8%A7%DB%8C-%DA%AF%D9%88%D9%86%D8%A7%DA%AF%D9%88%D9%86-%D9%81%D8%B1%D9%85%D8%AA-%DA%A9%D8%B1%D8%AF%D9%86-%D8%B1%D8%B4%D8%AA%D9%87-%D9%87%D8%A7-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-dvwf50gbvemy دریافت دایرکتوری دلخواه از خط فرمانلیست []argv فهرستی از ورودی ها را در خود نگه می دارد. پس از آنکه شما کد را درون فایل py. نوشتید، برای نمونه با دستور python3 YOUR_PYTHON.py /path/to/your/directory آن را اجرا می کنید پس ورودی به پایتون در اینجا ۲ تا است، یکی نام خود فایل پایتون و دیگری نام دایرکتوری یا مسیر منتهی به آن است.path = sys.argv[1] if len(sys.argv) &gt; 1 else &#039;.&#039;بنابراین [1]sys.argv یعنی دومین پارامتر درون لیست []argv که در اینجا همان نام یا مسیر دایرکتوری است. پس بررسی می شود که اگر اندازه لیست []argv بیشتر از ۱ باشد، یعنی نام فایل py. و نام یا مسیر دایرکتوری تعیین شده باشد، پس داریکتوری مشخص شده به متغیر path ریخته شود وگرنه اندازه لیست کمتر از ۲ یا برابر ۱ است و از این رو نام دایرکتوری مشخص نشده پس دایرکتوری جاری (Current Directory) که با نقطه پایان خط مشخص شده است به عنوان دایرکتوری ما تعیین می شود.توجه کنید این کد کمبود دارد و شما باید با ماژول os.path بررسی کنید اصلا آیا مسیر یا دایرکتوری وجود دارد؟راهنمای ماژولکد استفاده شده در این نوشته</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 02 Dec 2020 21:09:54 +0330</pubDate>
            </item>
                    <item>
                <title>دستور make و فایل MakeFile</title>
                <link>https://virgool.io/linux-internals/%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-make-%D9%88-%D9%81%D8%A7%DB%8C%D9%84-makefile-f3d2uuepnqyg</link>
                <description>در لینوکس (و دیگر سیستم عامل های شبه یونیکس) از کامپایلر gcc برای کامپایل کدهای سی استفاده می شود. خروجی یک برنامه دودویی است که می توان آن را اجرا کنیم. اگر شما از IDE هایی مانند CodeBlocks استفاده می کنید، اینها نیز gcc برای کامپایل می گیرند.gcc main.c -o outpu_bin_fileدر کد بالا گزینه o- برای تعیین نام و مسیر فایل دودویی خروجی استفاده می شود که این فایل دودویی اجرایی از تک فایل main.c ساخته می شود. اکنون گمان کنید که برنامه شما بسیار بزرگ است و چندین و چند فایل c.  دارد. در این حالت در صورت تغییر در یک فایل، به طور معمول همه فایل ها باید از نوع کامپایل (Recompile) شوند، حتی آنهایی که تغییری در آنها داده نشده است.اگر یک بسته کد منبع (Source Code Package) را تا کنون کامپایل کرده باشید، دیده اید که سه دستور زیر را به ترتیب اجرا کرده اید. در این میان دستور make  خودکار متوجه می شود که کدام بخش از یک فایل بزرگ نیاز به کامپایل دوباره دارد.configure
make
sudo make installراهنمای دستور make را با دستور man make بخوانید.درون MakeFile  چه چیزهایی استیک MakeFile‌ شامل یک مجموعه ازهدف ها (Targets) و  Dependencie ها و قاعده ها (Rules) است. یک هدف یا Target یک فایلی است که یا ساخته یا بروز رسانی می شود ولی می تواند یک عبارت (Directive) یا یک بر چسب باشد که توسط برنامه (دستور) make  مورد ارجاع قرار می گیرند.یک هدف وابسته به یک مجموعه از فایل های منبع (Source File)، یا Object File یا حتی یک دسته از Target های دیگر است که این وابستگی ها به گونه فهرستی از Dependency تعریف می شوند. قاعده ها یا Rule ها دستوهای هستند که برای ساخت (Build) هدف ها توسط نیازمندی ها نیاز هستند.زمانی که دستور  make یک MakeFile را می خواند، از روی مهرزمانی (Timestamp) متوجه می شود که کدام (فایل های) هدف (Target) باید ساخته (Build) شوند. اگر مهر زمانی تازه تر باشد، دستور make قواعد (دستورهای) متناسب با هدف را اجرا می کند.در شکل زیر یک نمونه از برنامه ای به زبان سی نشان داده شده است که دارای سه فایل کد منبع به نام های type.h (فایل سرآیند که اعلان تابع mysum و برخی از نوع ها یا ثابت ها را شامل می شود)، فایل mysum.c  (که بدنه تعریف تابع mysum را شامل می شود) و فایل t.c  که پیوست فایل سرآیند type.h و فایل سرآیند stdio.h و بدنه تابع main  را شامل می شود.برای کامپایل آن که دارای دو فایل کد سی به نام های mysum.c و  t.c  است دستور زیر را به کار برده ایم که در آن o- نام فایل دودویی خروجی را مشخص می کند که در اینجا آن را myt نامگذاری کرده ایم.gcc -o myt t.c mysum.cشکل زیر یک نمونه از makefile  را نشان می دهد که نام آن را همان نام معمول MakeFile گذاشته ام. در خط نخست نام Target  آمده است که در اینجا Target  ما همان فایل دودویی اجرایی به نام myt  است. پس از این نام علامت :  قرار گفته و سپس با یک فاصله فهرست وابستگی ها آورده شده است.فهرست وابستگی ها همان فایل هایی هستند که برنامه متکی به آنها است که شامل سه فایل type.h و  t.c و mysum.c است. سپس در خط بعدی که حتما باید با یک TAB آغاز شود، Rule  ها نوشته می شوند که در اینجا همان دستور gcc  است.myt: type.h t.c mysum.c                #target: dependency list
        gcc -o myt t.c mysum.c         # rules: line must begin with a TABاکنون اگر پیش از این فایل myt  را به کمک gcc ساخته اید، آن را پاک کنید و دستور زیر را انجام دهید. همانگونه که گفته شد، دستور make در لینوکس (و دیگر شبه یونیکس ها) فایل MakeFile را می خواند. البته هر فایلی makefile تلقی نمی شود و باید الگوی شکل نخست را داشته باشد که ساده ترین آن در سومین شکل بالا نشان داده شده است.make -f MakeFileدر دستور بالا، جلوی گزینه f- نام فایل makefile  می آید که در اینجا من آن را MakeFile گذاشته ام ولی شما می توانید هر نام دیگری مانند mk1 را بگذارید. پس از اجرای دستور بالا، خروجی زیر نشان داده می شود.gcc -o myt t.c mysum.c # rules: line must begin with a TABاین خروجی همان خط دومی است که با TAB آغاز شده بود و به Rule یا در اینجا دستور کامپایل اشاره می کرد. یادآور می شوم که مزیت استفاده از makefile و دستور make در این است که دستور make با بررسی مهر زمانی، تنها آن فایل هایی را دوباره کامپایل می کند که تغییری در آن رخ داده باشد، زیرا در لینوکس زمان آخرین تغییر (Modify Time) نگهداری می شود و اگر تغییری رخ داده باشد این زمان بروز و make  از آن آگاه می شود.اکنون اگر دوباره دستور make MakeFile را اجرا کنید می بینید که پیغام make: ‘myt’ is up to date نشان داده می شود که بدین معنی است که هیچ تغییری در کدهای برنامه انجام نشده است.شبیه سازی تغییر دادن زمان آخرین تغییر (Modify Time)در سسیتم عامل های یونیکسی دستوری به نام touch است که نام فایلی را دریافت می کند و سپس اگر آن فایل وجود نداشته باشد، آن فایل را می سازد و فیلدهای مختلفی مانند Access Time و  Modify Time را برای آن فایل تنظیم می کند.ولی اگر فایل از قبل وجود داشته باشد، پس تنها فیلدهای مد نظر را تغییر می دهد و چون یکی از این فیلدها Modify Time  است، پس از دید دستور make یک تغییر در فایل های کد منبع رخ داده است. در اینجا برای نمونه دستور زیر را انجام دهید.touch type.hبا این کار Modify Time فایل type.h  تغییر کرده، پس در اجرای دوباره دستور make -f MakeFile تنها همین فایل است که از نو کامپایل می شود. توجه کنید باز کردن و تغییر در یک فایل با هر ویرایشگری، نتیجه اش بروز شدن Modify Time است.منبعبرای فراگیری بیشتر می توانید به سایت زیر نگاهی بیاندازیدhttp://sysadmingeeks.irhttps://dataset-academy.comو یا می توانید در کانال تلگرام عضو شوید.https://t.me/datasetacademydotcom</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Sat, 04 Jul 2020 15:17:28 +0430</pubDate>
            </item>
                    <item>
                <title>فرمت های فایل های دودویی اجرا شدنی</title>
                <link>https://virgool.io/linux-internals/%D9%81%D8%B1%D9%85%D8%AA-%D9%87%D8%A7%DB%8C-%D9%81%D8%A7%DB%8C%D9%84-%D9%87%D8%A7%DB%8C-%D8%AF%D9%88%D8%AF%D9%88%DB%8C%DB%8C-%D8%A7%D8%AC%D8%B1%D8%A7-%D8%B4%D8%AF%D9%86%DB%8C-gxmafehuradi</link>
                <description>پس از نوشتن یک برنامه به هر زبانی مانند سی، سی پلاس پلاس، جاوا یا سی شارپ و دیگر زبان ها، کامپایلر می بایست که یک فایل دودویی از روی کد بسازد. این که این فرایند چگونه است، بحثی جدا را می خواهد ولی به هر رو، برآیند کامپایل یک فایل دودویی اجرا شدنی (Executable Binary File) است.Flat Binary Executableیک فایل Flat Binary Executable (یا FBE) یکی از فایل های دودویی اجرا شدنی است که تنها در برگیرنده کد اجرا شدنی (Executable Code) و داده های آغازین (Initialization Data) است. این گونه فایل دودویی اجرایی، برای اجرا شدن به به طور کامل درون حافظه بارگذاری شود. یک نمونه بارز از فایل دودویی اجرای FBE، فایل بوت سیستم عامل است که برای اجرا شدن، باید تماما در حافظه بارگذاری شود. در واقع FBE یک تک قطعه از کدهایی دودویی اجرا شدنی است که برای اجرا شدن به طور کامل درون حافظه بارگذاری می شوند.a.out Executable Fileیک فایل با پسوند out مانند a.out در آغاز دارای یک سرآیند (Header) است و سپس به دنبال آن بخش کد، سپس بخش داده ها و در پایان بخش BSS () است.ELF Executable Fileسرآغاز این فایل یک سرآیند به نام elf-header است که به دنبال یک یا چندین بخش برنامه (Program Section) می آید. در سیستم عامل لینوکس دستوری به نام readelf است که برای نمایش اطلاعاتی درباره یک فایل ELF به کار می رود.گمان کنید که یک فایل دودویی به نام GtkApp1 داریم و می خواهیم درون مایه آن را درباره فرمت ELF بدانیم. برای این کار می توانید دستور زیر را اجرا کنید که همه اطلاعات ELF را نشان می دهد. در شکل زیر می بینید که سرآغاز فایل سرآیند elf-header است.readelf -a GtkApp1فرمت ELF می تواند تا چندین بخش سرآیند برنامه (Program Header) داشته باشد که این امکان پذیر است که هر یک از این بخش ها درون یک فضای آدرس حافظه اصلی بارگذاری شوند. این فرمت فایل دودویی اجرای پیش فرض در سیستم عامل لینوکس است که برای پیوند پویا (Dynamic Linking) کارآتر و پسندیده تر است.در دومین شکل از بالا می توانید بخش سرآیندهای برنامه را ببینید. همچنین این فایل دودویی اجرایی بر پایه Dynamic Linking است که از این رو کتابخانه های اشتراکی یا در لینوکس Shared Object (فایل های با پسوند so) به کار گرفته می شوند که شکل زیر برای نمونه برنامه GtkApp1 این کتابخانه های اشتراکی را نشان می دهد. https://virgool.io/linux-internals/%DA%A9%D8%AA%D8%A7%D8%A8%D8%AE%D8%A7%D9%86%D9%87-%D9%87%D8%A7%DB%8C-%D8%A7%DB%8C%D8%B3%D8%AA%D8%A7-%D9%88-%D9%BE%D9%88%DB%8C%D8%A7-%D9%88-%D8%B4%DB%8C%D9%88%D9%87-%D9%87%D8%A7%DB%8C-linker-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-voruq0q7uju1 منبعبرای فراگیری بیشتر می توانید به سایت زیر نگاهی بیاندازیدhttp://sysadmingeeks.irhttps://dataset-academy.comو یا می توانید در کانال تلگرام عضو شوید.https://t.me/datasetacademydotcom</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Thu, 02 Jul 2020 16:20:07 +0430</pubDate>
            </item>
                    <item>
                <title>کتابخانه های ایستا و پویا و شیوه های Linker در برنامه نویسی</title>
                <link>https://virgool.io/linux-internals/%DA%A9%D8%AA%D8%A7%D8%A8%D8%AE%D8%A7%D9%86%D9%87-%D9%87%D8%A7%DB%8C-%D8%A7%DB%8C%D8%B3%D8%AA%D8%A7-%D9%88-%D9%BE%D9%88%DB%8C%D8%A7-%D9%88-%D8%B4%DB%8C%D9%88%D9%87-%D9%87%D8%A7%DB%8C-linker-%D8%AF%D8%B1-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-voruq0q7uju1</link>
                <description>دو روش برای ساخت یک برنامه دودویی اجرا شدنی یا Binary Executable هست: ۱) شیوه Static Linking و  ۲)  شیوه Dynamic Linking. در شیوه Static Linking از یک کتابخانه استاتیک یا Static Library کمک گرفته شده است.کتابخانه های ایستا و اشتراکی چه هستنددر این شیوه، برنامه موسوم به Linker (پیوند دهنده) همه ی کد تابع کتابخانه و همه داده ها را درون یک فایل دودویی اجرایی  با پسوند out برای نمونه a.out نگهداری می کند. البته این پسوند out اجباری نیست و می توانید آنرا ننوسید. در دستور زیر می بینید که خروجی دودویی اجرایی برنامه سی، بدست گزینه o- ساخته می شود که در اینجا آن را a.out نامگذاری کرده ایم ولی بایدی برای بودن پسوند out نیست. برای کامپایل یک برنامه نوشته شده به زبان C می توانیم از خط فرمان و از کامپایلر gcc (کوتاه شده GNU C Compiler) به گونه زیر کمک بگیریم:gcc my_c_program.c -o a.outاین شیوه پیوند دهنده ایستا خوب است، زیرا که هر آنچه که برای اجرای فایل دودویی اجرا شدنی نیاز داریم، همگی در یک فایل هستند، ولی اندازه فایل بسیار زیاد خواهد شد.شیوه دیگر، Dynamic Library است، که در آن به جای استفاده از Static Library، از Shared Library کمک گرفته می شود. در این شیوه، دیگر همه کتابخانه ها درون فایل a.out نگهداری نمی شوند، بلکه فراخوان هایی (Call) به تابع های استفاده شده به ریخت یک Directive در فایل a.out نگهداری می شوند.هرگاه که یک فایل a.out به گونه پیوند پویا را اجرا می کنید، وظیفه سیستم عامل است تا هم فایل a.out و هم کتابخانه های نیاز آن را درون حافظه بارگذاری کند. از این رو درون حافظه برنامه دودویی اجرا شدنی به کدهای مورد نیازش دسترسی دارد.بنابراین در شیوه پیوند پویا، به جای آن که کتابخانه ها به ریخت ایستا درون خود فایل a.out نگهداری شوند، هر زمان که برنامه a.out اجرا شد، سیستم عامل کتابخانه های نیاز را به درون حافظه بارگذاری می کند و از این رو از بزرگ شدن بی دلیل و بی سود فایل دودویی اجرایی، جلوگیری می شود.سودمندی های فایل a.out کاهش اندازه فایل بسیاری دیگر از برنامه ها، به کتابخانه های اشتراکی همسانی نیاز دارند که اکنون برای همگی در حافظه بارگذاری شده اند. چرایی برجسته دیگر برای به کار گیری Dynamic Linker در این است با دگرگونی در یک کتابخانه، دیگر نیازی نیست که خود فایل a.out را از نو کامپایل کنیم.در سیستم عامل ویندوز با واژه کوتاه شده DLL را شنیده باشید که کوتاه شده Dynamic Linking Librarie است. این کتابخانه های شناخته شده به نام DLL کتابخانه های اشتراکی هستند که در کنار (و نه درون) فایل دودویی اجرایی، در حافظه بارگذاری می شوند.در سیستم عامل لینوکس، کتابخانه های اشتراکی به نام Dynamically Loaded یا کوتاه شده DL شناخته می شوند. بنابراین کتابخانه های اشتراکی زمانی در حافظه بارگذاری می شوند که به آنها نیاز باشد و این نقطه پیش روی کتابخانه های ایستا است که همیشه درون فایل دودویی اجرایی هستند. کتابخانه های DL برای ماژول هایی پویا درون حافظه بارگذاری می شوند، بسیار سودمند و کاربردی هستند.توجه کنید، زمانی کتابخانه های اشتراکی به درون حافظه بارگذاری می شوند که یک برنامه دلخواه اجرا شده باشد. با اجرای یک برنامه، پیش از دادن پردازنده برای اجرا شدن آن، نیاز است تا آن برنامه در حافظه صف بندی شود و در همین زمان است که کتابخانه های آن به درون حافظه بارگذاری می شوند.منبعبرای فراگیری بیشتر می توانید به سایت زیر نگاهی بیاندازیدhttp://sysadmingeeks.irhttps://dataset-academy.comو یا می توانید در کانال تلگرام عضو شوید.https://t.me/datasetacademydotcom</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Thu, 02 Jul 2020 14:30:32 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش های رایگان کامپیوتر</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%87%D8%A7%DB%8C-%D8%B1%D8%A7%DB%8C%DA%AF%D8%A7%D9%86-%DA%A9%D8%A7%D9%85%D9%BE%DB%8C%D9%88%D8%AA%D8%B1-hfjhqdixfa0l</link>
                <description>با درود و خسته نباشیددر این مدت هر چند بسیار بسیار اندک تلاش کردم تا در سایت گوگل مجموعه ای از آموزش هایی درباره کامپیوتر را فراهم کنم.پیش از نوشتن در ویرگول، در سایت دیگری به نام http://dataset-academy.com می نوشتم و به امید خدا، بازهم خواهم نوشت.پیش از نوشتن در ویرگول، در سایت دیگری به نام https://dataset-academy.com می نوشتم و به امید خدا، بازهم خواهم نوشت.پس از انکه سایت بازدهی مالی درستی نداشت، برآن شدم تا محتوای آن را که باید بگویم نیاز به کار بیشتری دارد را از دیروز به رایگان در دسترس قرار دادم و به امید خدا از این پس نیز رایگان خواهم نوشت.بنابراین از شما می خواهم از این سایت را ببینید شاید مطلبی باشد که به کار شما بیایید.امیدوارم سودمند باشد.https://dataset-academy.com</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 05 Jun 2020 16:06:16 +0430</pubDate>
            </item>
                    <item>
                <title>سایت آموزش لینوکس پیشرفته</title>
                <link>https://virgool.io/linux-internals/%D8%B3%D8%A7%DB%8C%D8%AA-%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA%D9%87-zalvgyyhmhgh</link>
                <description>با درود به شما دوستان گرامیسال نو شما شاد و خجسته بادآرزوی سالی سرشار از شادی و پیروزی و بهروزی و تندرستی و بی نیازی براتون دارمپس از زمانی که تصمیم داشتم سایتی درباره لینوکس و آشنایی با مفاهیم بنیادی سیستم عامل ها و هسته لینوکس راه اندازی کنم، چند روز پیش سایتی به نام http://sysadmingeeks.ir را راه اندازی کردم با انگیزه برای آموزش مفاهیم سیستم عامل، هسته لینوکس و برنامه نویسی سی. سایت در آغاز راه هست و من چون عادت دارم همیشه یک سری از آموزش های پیش زمینه رو آماده کنم تا به پیشرفته برسیم، پس نوشته های کنونی سایت هنوز وارد بحث های سیستم عامل و برخی دیگر از مفاهیم نشدند. به طور کلی انگیزه ام برای راه اندازی سایت در آغاز کار:آموزش زبان سی و ساختارهای دادهآموزش مفاهیم بنیادی سیستم عاملآموزش و نگاهی بر هسته لینوکس و زیر سیستم های آن همچون مدیریت حافظه تا زیر سیستم شبکهو اگر خدا یاری کند که بتوانم در آینده همچنان ادامه دهممفاهیم پایگاه داده و نگاهی بر الگوریتم های آنمفاهیم سیستم های توزیع شده از سیستم محاسبات توزیع شده مانند کلاستر تا HPC و گرید.پس شما رو دعوت می کنم سایت رو ببینید و در اینجا یا در خود سایت دیدگاه خودتان را به من بگوید.http://sysadmingeeks.irشاد باشید.</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Sun, 29 Mar 2020 00:56:09 +0430</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش هشتم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%87%D8%B4%D8%AA%D9%85-g0duvfxiuz6l</link>
                <description>در نوشته پیشین تا اندازه ای درباره ساخت پیغام در سوکت های TCP و چالش پیش رو گفتیم. چالشی که بررسی شد، اندازه (Length) یک پیام یا داده فرستاده شدنی بود. چالش دیگری که پیش خواهد آمد، ترتیب بایت ها است. در نوشته زیر درباره دو مفهوم Big Endian و Little Endian گفتگو کردیم. https://virgool.io/@linux_internals/%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-little-endian-%D9%88-big-endian-rt5c3ailish0 همچنین در سری نوشته های &quot;آشنایی با سوکت های شبکه در سی و لینوکس&quot; درباره مفهوم Network Byte Order گفتیم که برای استاندارد سازی بایت های فرستاده شده در شبکه، از الگوی Big Endian کمک گرفته می شود تا مستقل از سیستم عامل یا سیستم های دو سوی شبکه، یک شیوه برای ترتیب بایت های شبکه به کار گرفته شود.حتی با به کارگیری از struct برای ساخت پیام ها برای پوشش اندازه پیام، بازهم ایرادی پیش خواهد آمد و این است که اگر قاعده ای پذیرفته شده برای ترتیب بایت شبکه نباشد، با اینکه داده ای درست به سوی دیگر فرستاده می شود ولی در سوی دیگر چون داده به گونه ای دیگری تفسیر و درک می شود، زیرا ترتیب بایت را متفاوت است.هچنین در نوشته های پیشین درباره چهار تابع به نام های ()htons و ()htonl و ()ntohs و ()ntohl گفته ایم که به ترتیب دو تای نخست برای تبدیل داده ها قابل خواندن برای کاربر به ترتیب بایت های شبکه (Big Endian) و دو تای پایانی برای تبدیل بایت های شبکه به نمایش قابل خوانده شدن توسط کاربر به کار گرفته می شوند.یادآوری: آنهایی که پایان نامشان s دارند برای داده های short که ۱۶ بیتی (۲ بایت) و آنهایی که l دارند برای داده های long که ۳۲ بیت (۴ بایت) هستند.msgStruct.dep = htonl(deposit);
msgStruct.wd = htonl(withdrawals);
send(s, msgStruct, sizeof(msgStruct), 0); https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%BE%D9%86%D8%AC%D9%85-ephuzqarrm9c  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B4%D8%B4%D9%85-siqfddwwsbd4  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%87%D9%81%D8%AA%D9%85-xs4cc4nzktkt هم تراز سازی و Paddingآنچه که از نوشته بخش هفتم تا کنون گفته شده است، درباره پیغام هایی است که میان دو سوی شبکه تبادل می شوند. در واقع می خواهیم پیام هایی را میان دو برنامه (یا فرایند) تبادل کنیم که از راه سوکت ها در روی شبکه با یکدیگر ارتباط دارند.این پیام رسانی (Message Passing) تنها برای دو فرایند یا برنامه بر روی دو رایانه در شبکه نیست و درون یک سیستم با چندین پردازنده (یا هسته) یا درون یک سیستم توزیع شده می تواند که نیاز باشد تا فرایندها با یکدیگر تبادل پیام بکنند.بنابراین در چنین موردهایی، باید در سطح برنامه (Application Layer) فرمت پیام بی ابهام شناسانده شده باشد و در بخش هفتم نشان دادیم که در زبان های سی و سی پلاس پلاس این کار (ساخت پیام با فرمت بی ابهام) به کمک struct انجام می شود.زمانی که پیام دارای چندین فیلد کد شده دودویی باشد، باید مفهومی به نام هم تراز سازی را در نظر بگیریم. هم تراز سازی داده ها یا ساختارهای داده (Data Structure Alignment)، نحوهٔ چینش و دسترسی به اطلاعات حافظه رایانه رایانه توسط پردازندهٔ رایانه است.در زبان های برنامه نویسی هر شی (متغیر) دارای دو شناسه مقدار و آدرس فضای حافظه اصلی است. داده ها در حافظه اصلی می توانند در اندازه های ۱، ۲، ۴، ۸ بایت یا به طور کلی توان هایی از دو نگهداری شوند. برای نمونه، می خواهیم در کنار مقدارهای int و ۴ بایتی سپرده و پرداخت ها، می خواهیم شمارِ تراکنش های سپرده ها و برداشت ها را با دو فیلد short int که هر یک ۲ بایت را اشغال می کنند، به گیرنده بفرستیم.توجه کنید برای این short int را برگزیدیم، زیرا که شمار سپرده ها و برداشتی ها بیش از ۶۵۵۳۵ نمی شود. بنابراین چیدمان یا تراز پیام دلخواه ما بدین گونه است که: ۴ بایت برای اندازه سپرده، ۲ بایت برای شمار تراکنش های سپرده، ۴ بایت برای پرداشت ها و در پایان ۲ بایت برای شمار تراکنش های برداشتی ها را در خود دارد.Message Alignmentstruct {
        int centsDeposited;
        unsigned short numDeps;
        int centsWithdrawn;
        unsigned short numWd;
} msgBuf;
// struct member value assignment
send(s, &amp;msgBuf, sizeof(msgBuf), 0);اندازه این struct باید ۱۲ بایت باشد ولی باید گفت که همیشه ماشین ها این (پیام) ۱۲ بایت را نمی سازند، بلکه ۱۴ بایت را خواهند ساخت. این دو بایت مازاد را Padding Bytes می گویند که در ساختار بالا و درون حافظه اصلی میان  numDeps و centsWithdrawn قرار می گیرد.برای تراز کردن داده ها در حافظه، یک یا چند بایت تهی (فضای آدرس حافظه اصلی) میان آدرس های حافظه که در هنگام اختصاص حافظه برای اعضای دیگر ساختار (struct) اختصاص داده شده است (یا خالی مانده) درج می شود. این مفهوم را Padding می نامند.چرایی اینکه این ۲ بایت مازاد پدید می اید برای این است که در پردازنده های معماری ۳۲ بیتی، پردازنده هر بار یک واژه (کلمه - Word) یا ۴ بایت را از حافظه بر می دارد. بنابراین برای برآوردن این نیاز، همیشه داده ها در ۴ بایت در حاظفه تراز می شوند. بنابراین Padding آدرس های مازاد و تهی است. Data Alignment with Padding Bytesراهکار برای پوشش و از میان برداشتن Padding چیست؟ راهکار بسیار ساده است و به کد نویسی باز می گردد. یک بار دیگر چرایی اینکه در دستورهای بالا Padding رخ داده است را می گوییم، زیرا دستور unsigned short numDeps را پیش از int centsWithdrawn نوشته شده است و یک فضای تهی ۲ بایتی را برای ساختن ۴ بایت نیاز خواهد داشت. پس اگر جای نوشتن متغیرها را مانند زیر تغییر دهیم دیگر Padding رخ نمی دهد.struct {
        int centsDeposited; 
        unsigned short numDeps;
         int centsWithdrawn;
         unsigned short numWd;
} msgBuf;بنابراین با کد بالا، چیدمان و تراز داده ها درون پیام (حافظه اصلی) به دسرتی انجام خواهد شد و اکنون پیام فرمتی همانند نخستین شکل با ۱۲ بایت را خواهد داشت. شاد و پیروز و تندرست و بی نیاز باشید.</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 20 Mar 2020 21:54:25 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش هفتم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%87%D9%81%D8%AA%D9%85-xs4cc4nzktkt</link>
                <description>در نوشته بخش ششم درباره ساخت سوکت TCP گفته شد. در این نوشته می خواهم درباره چگونگی ساخت پیغام (Construct Message) برای پروتکل TCP در ارتباط شبکه به کمک سوکت آموزشی از کتاب TCP IP Sockets in C Practical Guide for Programmers و برخی دیگر از منابع بدهم. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%BE%D9%86%D8%AC%D9%85-ephuzqarrm9c  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B4%D8%B4%D9%85-siqfddwwsbd4 پروتکل TCP اتصال گرا (Connection Oriented) است و ارتباطی پایدار را میان دو سوی شبکه فراهم می کند ولی این پروتکل هیچ دیدی نسبت به پیغام های فرستاده شده ندارد. سوکت ابزاری برای ارتباط و تبادل پیغام و اطلاعات میان دو سوی شبکه است، از این رو، فرستنده و گیرنده باید بر سر اینکه چگونه این اطلاعات کد گذاری (Encode) شوند به توافق رسیده باشند.در واقع به دنبال یک پروتکل میان فرستنده و گیرنده هستیم که هر دو آن را پذیرفته اند. پروتکل به زبان ساده، یک دسته از قوانین و رویه ها است که میان دو نفر مشترک است. برای نمونه، زبان انگلیسی، امروزه پروتکلی است که دو نفر می توانند با آن و بر اساس یک سری از واژه و دستور زبان و جمله سازی، با یکدیگر گفتگو کنند.در رایانه ها نیز همین گونه است و پروتکل تنها در پیوند با لایه برنامه (Application Layer) نیست، بلکه در لایه های دیگر TCP/IP نیز پروتکل هایی فراهم شده اند که دو لایه همسان در دو سوی شبکه با یکدیگر گفتگو کنند. در همین راستا، در سوی فرستنده، در هر لایه از بالا به پایین، یک سری از اطلاعات به بسته شبکه (Network Packet) افزوده می شود که در سوی دیگر، در گیرنده، از پایین به بالا، این اطلاعات در همان لایه برداشته و خوانده می شوند.پروتکل به زبان سادهاطلاعات چگونه کد گذاری شوند.فرمت پیغام چیست.اندازه (Length) پیغام چه اندازه است.چگونه یک ارتباط با پایان یابد.پروتکل TCP بر پایه فریم ها (Frame) است و انعطاف بالایی را برای آماده سازی پیام ها می دهد. شکل زیر ساختار ساده ای از یک پیغام را نشان می دهد که در Cassandra به کار گرفته شده و CQL نام دارد. همانگونه که می بنید پیام از چندین فیلد (Field) جدا از هم ساخته شده است که هر فیلد یک داده ویژه را نگهداری می کند.CQL binary protocolآنچه که ما به دنبال آن هستیم، پروتکلی در سطح برنامه (Application Protocol) است که نیاز دارد تا آشکار بگوید که داده ها (پیغام ها) چگونه باید به دست فرستنده پیام فرمت شوند تا در سوی دیگر، گیرنده بتواند آن را پردازش و درک کند و داده هایی معنا دار را از آن بدست آورد.گمان کنید می خواهیم دو شماره int x, y را از یک برنامه به برنامه دیگر بفرستیم. برای یکپارچه بودن داده ها میان فرستنده و گیرنده، باید این دو داده به گونه ای توافق شده کدگذاری شوند وگرنه ایرادهایی پدید خواهد آمد. برای نمونه، داده های بانکی که باید فرستاده شوند که یکی از شماره ها نشان دهنده سپرده (Deposit) و دیگری نشان دهنده برداشت (Withdrawal) است. در این نوشته و بر پایه کتاب گفته شده چندین متغیر هست که در آن کتاب به کار رفته است.متغیر deposit برای اشاره به سپرده.متغیر withdrawals برای اشاره به برداشت ها.متغیر s که به توصیفگر فایل سوکت TCP اشاره دارد.برای ماشین و کامپایلر، اندازه (sizeof(int برابر با ۴ بایت و (sizeof(short برابر با ۲ بایت است.کدگذاری داده هابنابراین در اینجا به دنبال کد کردن این دو مقدار (متغیر) هستیم. یک راه این است که از کد گذاری نویسه ای (Character Encoding) کمک بگیریم. در واقع این دو مقدار شماره int را به رشته هایی از شماره های دهدهی چاپ شدنی کد می کنیم.یک کد گذاری ساده، کد گذاری اَسکی (ASCII) است که توالی از بایت ها است که هر مقدار آن متناظربا یک کد اسکی است. برای نمونه دو شماره 17998720 و 47034615 را می توانیم همانند شکل زیر در یک توالی از کدهای اسکی کد گذاری کنیم. در میان کدهای اسکی، کد شماره 48 برای شماره 0 و کد شماره 57 برای شماره 9 است. همچنین کد شماره 32 برای جدا کننده به کار رفته است، زیرا 32 کد اسکی تک فضای خالی (Space) است.ASCII Tableبنابراین در اینجا یک کد گذاری ساده برای دو شماره انجام دادیم که جدا کننده این دو شماره درون بایت کد شده فضای خالی است. در کنار به کارگیری از تک فضای خالی می توانستیم از کد اَسکی کاراکتر Null Terminator، یعنی کاراکتر 0\ یا از یک Tab کمک بگیریم. در شکل زیر که رشته کد شده را نشان می دهد، نخستین شماره برای سپرده و دومین برای برداشت ها است.Encoded Dataبنابراین اگر پیام آماده شده تنها در برگیرنده همین دو شماره باشد، پس اندازه آن ۱۸ بایت می شود. اکنون گمان کنید یک متغیر (کاراکتری از رشته ها) به نام msgBuffer داشته باشیم، می توانیم دو شماره (متغیر) را با تابع ()sprintf فرمت و آماده کنیم.sprintf(msgBuffer, &amp;quot%d%d &amp;quot,  deposit,  withdrawals);
send(s, msgBuffer, strlen(msgBuffer),  0);ایرادهاتوجه کنید که در پایان رشته کد شده نیز یک جدا کننده فضای خالی هست، زیرا با آن نیز مقدار برداشت شناخته می شود. اگر این نیز نباشد، پس برنامه (سوی دیگر شبکه) نمی تواند آنچه که به دنبال شماره برداشت شاید باشد را شناسایی کند.دومین ایراد این است که متغیری که بافر (در اینجا msgBuffer) را نگه می دارد، باید به اندازه ای کافی بزرگ باشد تا بیشترین اندازه بایت کد شده رادر خودش نگه دارد. به زبان ساده، باید همه رقم های شماره ها و همچنین در صورت بودن، علامت منفی، دو فضای خالی جدا کننده و کاراکتر Null Terminate را نیز نگه دارد.اگر هر شماره دارای ۹ رقم باشد، پس رشته کد شده نهایی ۲۳ بایت می شود، زیرا برای هر رقم ۲ بایت، برای هر فضای خالی نیز ۲ بایت و برای کاراکتر Null Terminate نیز ۱ بایت را در بر می گیرند. آیا این ۲۳ بایت اندازه ای برای رشته کد شده در برنامه است؟ اگر شماره ای چند رقم بیشتر داشته باشد، برنامه ار نخواهد کرد.سومین ایراد این است که در تابع ()send بالا، سومین ورودی، تابع ()strlen تنها بایت هایی را در نظر می گیرد که دو شماره را می سازند. به گفته دیگر، بایت پایانی، یعنی کاراکتر NULL را رَد می کند و از این رو، اندازه برگشتی رشته بایت کد شده، یکی کمتر خواهد بود.در کد زیر یک ماکرو تعریف شده است که اندازه بافر، یعنی ۱۳۲ بایت را مشخص می کند. سپس یک آرایه به نام msgBuffer ساخته شده که اندازه کلی آن برابر با ماکرو BUFSIZE است. سپس همه این آرایه ۱۳۲ بایتی بی توجه به اندازه پیام فرمت شده به گیرنده فرستاده می شود، پس در گیرنده، پیامی با اندازه ای بزرگ دریافت شده که تنها بخشی از آن داده های کد شده هستند.#define BUFSIZE 132
// Another Codes
char msgBuffer[BUFSIZE]
// Another Codes
sprintf(msgBuffer, &amp;quot%d%d &amp;quot,  deposit,  withdrawals);
send(s, msgBuffer,  BUFSIZE,  0);بنابراین کد گذاری شماره ها به رشته های (اَسکی)، شیوه کارآمدی نیست. هر بایت در رشته کد شده یکی از شماره های صفر تا نه است که هر شماره تنها ۴ بیت (و نه یک بایت) را نیاز دارد و این برای تغییر داده های شماره ای کد شده پسندیده نیست.برای نمونه، اگر نیاز باشد تا پردارشی (مانند جمع - تفریق) روی داده ها در سوی دیگر انجام دهیم، پس نیاز است تا یک تبدیل از String به Integer انجام شود. برای پوشش اندازه پیغام فرستاده شده، در زبان سی  ساختار ها (struct) برای ساخت پیغام به کار می رد.یک struct در زبان سی و سی پلاس پلاس، ساختاری است که از یک تا چندین عضو ساخته شده است که هر نوع می تواند از یک گونه بومی باشد. مانند int, float, double, char, bool یا آرایه ای از داده ها مانند [] int یا [] char) یا اشاره گر ها مانند * char که به یک رشته از توالی کاراکترها اشاره دارد. همچنین یک struct می تواند عضوی از گونه struct دیگری داشته باشد.از struct برای نمایش یک موجودیت مانند یک نفر کمک گرفته می شود. این نفر دارای نام، نام خانوادگی، سن، شمار فرزندان است. در کنار این، می تواند یک struct دیگر را درون خودش داشته باشد که به مشخصه های پدر و مادر او اشاره دارد.در زیر نمونه کدی نشان داده شده است که یک ساختار ساخته شده است. این ساختار یک الگو یا فریم پیام ساده TCP را نشان می دهد که دارای دو عضو به نام dep (اشاره به deposit) و wd (اشاره به withdrawals) از گونه int است.struct{
        int dep;
        int wd;
} msgStruct;
// Another Codes
msgStruct.dep = deposit;
msgStruct.wd   = withdrawals;
send(s, &amp;msgStruct, sizeof(msgStruct), 0);اندازه یک شی مانند int یا short در سی به کمک تابع ()sizeof بدست می آید. اندازه struct ها برابر با مجموع اندازه بایت هایی است که هر عضو آن اشغال می کند. برای نمونه int اندازه ۴ بایت را اشغال می کند، پس ساختار بالا در کل ۸ بایت را نیاز دارد، بی توجه به اینکه آن را به رشته اَسکی تبدیل کنیم که دارای یک کاراکتر NULL است.پروتکل TCP بسیار انعطاف پذیر است و می توانید دوبار به کمک ()send مقدار های متغیرهای deposit و withdrawals را بفرستیم. در واقع شیوه دیگر این است که در TCP خود متغیر را بفرستیم ولی این در UDP شدنی نیست، زیرا دو دیتاگرام (Datagram) جدا از هم برای هر متغیر فرستاده می شود.بنابراین در هر یک از دو شیوه (فرستادن تک تک متغیرها یا کمک از struct)، یک توالی از بایت ها همزمان فرستاده می شوند. این توالی از بایت ها از دو تا ۴ بایت برای هر int ساخته شده است. البته باز هم یک ایراد هست و این است که در ماشین (سیستم عامل) های گوناگون شاید نمایشی ناهمسان از int باشد که در این باره در نوشته های پیشین گفتیم روش استاندارد در شبکه، به کارگیری Big Endian یا Network Byte Order است.تا نوشته دیگر، شاد و پیروز و تندرست باشید.      </description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 20 Mar 2020 00:40:56 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش ششم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B4%D8%B4%D9%85-siqfddwwsbd4</link>
                <description>در دنباله نوشته های آشنایی با سوکت های شبکه در سی و لینوکس، در این نوشته می خواهیم چگونگی ساخت یک برنامه سوکت محور با سی و در سیستم عامل لینوکس را بر پایه پروتکل TCP نشان دهیم. سوکت های شبکه دارای آدرس فامیلی AF_INET برای IPv4 و AF_INET6 برای IPv6 هستند. همچنین اگر بخواهیم پروتکل TCP را به کار ببریم، باید SOCK_STREAM یا SOCK_DGRAM برای UDP را به دومین ورودی بفرستیم. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt فهرست فایل های سرآیند که نیاز هستندفایل stdio.h برای تابع های ()printf و ()fprintfفایل sys/socket.h برای تابع های ()socket و ()bind و ()connectفایل arpa/inet.h برای ساختار struct sockaddr_in و تابع ()inet_ntoaفایل stdlib.h برای تابع ()atoiفایل string.h برای تابع ()memsetفایل unistd.h برای تابع ()closeدر این نوشته از دو کد سرور و کلاینت این سایت کمک گرفته شده است، پس پیشنهاد می شود همزمان با خواندن این نوشته، این کدها را نیز داشته باشید.کد سروروظیفه سرور، گوش دادن به درخواست های ورودی از سوی کلاینت ها است، بنابراین کد (یا برنامه سرور) باشد نخست آماده و اتصالی را بر روی سوکت با نشانی IP یا شماره پورت برقرار کند. در سوی سرور نخست باید یک سوکت با ()socket ساخته شود که برگشتی این تابع یک شماره صحیح است که در واقع شماره توصیفگر فایل به سوکت است. همچنین می توانیم یک سری از گزینه ها را برای سوکت به کمک تابع ()setsockopt مشخص کنیم.در نوشته پَسین درباره این گزنه ها و تابع های ()setsockopt و ()getsockopt را آموزش خواهم داد.سپس باید با ساختار struct sockaddr_in یک دوتایی (IP, Port) را به همراه آدرس فامیلی مشخص می کنیم، زیرا هر سوکت یک دوتایی IP و Port است. سپس باید به کمک ()bind این دوتایی را به سوکت ساخته شده با ()socket انقیاد (Bind) کنیم.اکنون نوبت به فراخوانی تابع ()listen است، زیرا باید سرور آماده گوش دادن به درخواست های ورودی از روی شبکه باشد. یک درخواست از سوی کلاینت با دو مولفه نشانی IP و شماره پورت مشخص می شود. برای نمونه زمانی اگر فرض کنیم در یک شبکه محلی LAN، ماشین سروری هست که روی آن تنها یک کارت شبکه هست که نشانی آن 192.168.1.100 است و شماره پورت 9090 را مشخص کرده ایم، پس دوتایی سوکت سرور بر روی آن گوش می دهد و  کلاینت ها آن را برای یک درخواست به کار می برند، 192.168.1.100:9090 است.آدرس 0.0.0.0 به همه آدرس های روی یک ماشین اشاره دارد که در نوشته بخش چهارم گفتیم با INADDR_ANY مشخص می شود.تابع ()listen به درخواست های ورودی گوش می دهد و ر دنباله، تابع ()accept یک درخواست ورودی را می پذیرد. خروجی این تابع، یک سوکت تازه است که در واقع همانند ()socket، یک شماره شناسه برای توصفیگر فایل است.همانگونه که گفته شد، سوکت به ریخت فایل ها در لینوکس و سیستم عامل های شبه یونیکس پیاده سازی می شوند. بنابراین خواندن و نوشتن بر روی آنها در هسته، چیزی همانند خواندن و نوشتن روی فایل ها است. در واقع تابعی به نام ()read است که از روی توصیفگر فایل برگشتی از تابع ()accept، بافر به بافر می خواند.سرور در کنار اینکه می تواند از کلاینت ها پیغام ها و داده هایی را دریافت کند، می تواند به کمک تابعی به نام ()send به کلاینت پاسخی را نیز بفرستد که در ساده ترین گونه، یک پیغام ساده رشته ای است. بنابراین در سوی کلاینت به کمک ()recv، یک پیغام یا داده به سرور فرستاده شده است.شکل زیر چند خط نخستین از درون تابع ()main را نشان می دهد. در خط ۱۰ سه متغیر int تعریف شده است که به ترتیب برای ذخیره سازی برگشتی تابع های ()socket و ()accept و ()read نگهداری می شوند. سپس یک متغیر از نوع struct sockaddr_in ساخته ایم. متغیر opt از نوع int برای به کارگیری درون ()setsockoptبه کار می رود.تابع ()sizeof اندازه بایت های اشغال شده توسط یک متغیر را برگشت می دهد. در خط ۱۳ اندازه متغیر address که از نوع struct sockaddr_in است را در متغیر addrlen می رزیم. متغیر buffer آرایه ای کاراکترها یا رشته ای به طول 1024 است که سپس درون تابع ()read به کار می بریم تا بافرهای خوانده شده از روی سوکت در آن نگهداری شوند. در پایان یک اشاره گر از کاراکتر که در واقع رشته اَسکی است را نوشته ایم که پیغام پاسخ سرور به کلاینت را در خود نگهداری می کند.سپس در یک شرط if در خط های ۱۷ تا ۲۱ بررسی می شود که آیا توسکت به کمک تابع ()socket به درستی ساخته شده است. نتیجه برگشتی ()socket در صورت اجرای درست، باید شک شماره صحیح مثبت و نامنفی باشد. بنابراین شرط خط ۱۷ همین را بررسی می کند. توجه کنید چون می خواهیم برای IPv4 سوکت TCP بسازیم پس ورودی های یکم و دوم به ترتیب AF_INET و SOCK_STREAM هستند.تابع ()perror یک خطای سیستمی را بر روی Standard Error نشان می دهد. این تابع در stdio.h شناسانده شده است.تابع ()exit روند بیرون آمدن یا پایان یافتن برنامه را انجام می دهد. EXIT_SUCCESS و EXIT_FAILURE به ترتیب دو ثابت در سی استاندارد هستند که به همراه تابع ()exit در stdlib.h شناسانده شده اند.برای بیرون آمدن عادی و بی خطا در زبان های برنامه نویسی مانند سی و سی پلاس پلاس و پایتون، معمولا شماره صفر را به تابع ()exit می فرستند و از این رو ثابت EXIT_SUCCESS برابر با شماره صفر است. شماره 1- را نیز برای بیرون آمدن با خطا به کار می برند. البته می تواند شماره های دیگر مانند 2- را نیز برای شرایط دیگر خطا به کار برد.شرط if خط های ۲۳ تا ۲۷ نیز نخست تلاش می کند تا گزینه های سوکت را با ()setsockopt تنظیم کند. اگر این کار به خطا دچار شود، پس همانند پیش، تابع های ()perror و ()exit فراخوانی می شوند. در نوشته دیگری درباره گزینه های سوکت خواهم گفت.اکنون باید یک نمونه از ساختار struct sockaddr_in را مقداردهی کنیم . پیش از این متغیری به نام address را ساخته بودیم که اکنون مقدار هر عضو آن را مشخص کرده ایم. همچنین می بینید که به کمک ()htons شماره پورت را به بایت شبکه تبدیل کرده ایم. توجه کنید در خط ۳۱ نام یک ماکرو به نام PORT را به تابع ()htons فرستاده ایم که در واقع این ماکرو به کمک دستور زیر، پیش از تعریف تابع ()main انجام شده است.#define PORT 9090سپس باید به کمک ()bind نشانی IP و شماره درگاه را به سوکت انقیاد کنیم. ورودی یکم این تابع همان متغیری است که برآیند تابع ()socket است. ورودی دوم در شکل زیر نشان می دهد که یک تبدیل (Cast) از ساختار struct sockaddr_in به ساختار struct sockaddr است.در نوشته های پشین گفتیم که می توانیم ساختار struct sockaddr_in را به ساختار عمومی struct sockaddr تبدیل (Cast) کنیم.سپس باید تابع ()listen را فراخوانی کنیم که دو وروی را دریافت می کند. ورودی یکم نم متغیری است که برآیند تابع ()socket را در خودش نگه می دارد. ورودی دوم یک شماره صحیح که نام آن blocking است. این شماره، بیشینه اندازه یک صف انتظار اتصال ها را نشان می دهد که تا این اندازه می تواند رشد کند. توجه کنید برآیند ()listen نیز یک شماره صحیح (و نه یک شماره توصیفگر فایل) است که اگر کمتر از صفر باشد، پس خطایی رخ داده است.اکنون باید تابع ()accept فراخوانی شود که یک درخواست ورودی را می پذیرد. این تابع سه ورودی دارد که نخستین آنها نام متغیری است که برآیند ()socket در آن نگهداری می شود. دومین ورودی همانند ()bind یک تبدیل از struct sockaddr_in به struct sockaddr است.سومین ورودی یک تبدیل از int به socklen_t است. socklen_t یک گونه شناسانده شده در فایل sys/socket.h است که به گونه صحیح بی علامت ۳۲ بیتی اشاره می کند. توجه کنید متغیر addrlen که برآیند تابع ()sizeof را در خودش نگه می دارد از گونه int است و در سومین ورودی به socklen_t تبدیل می شود. همچنین توجه کنید که برآیند ()accept یک سوکت تازه است که در واقع به سوکت سوی کلاینت (در کد سرور) اشاره می کند که در اینجا نام آن new_socket است.تابع ()read برای خواندن داده هایی است که از سوکت فرستاد شده است و از این رو در سوی سرور، یکمین ورودی آن نام متغیری است که سوکت سوی کلاینت (در اینجا new_socket) را در خودش نگه می دارد. دومین ورودی نام متغیری است که قرار است بافر ورود ها باشد که در اینجا همان متغیر آرایه ای از کاراکترهای  ۱۰۲۴ بایتی است. سومین وررودی، اندازه ای به بایت است که نشان می دهد تا چه اندازه باید بایت به بایت بخوانیم که این همانند اندازه بافر (۱۰۲۴) بایت است.سپس با تابع ()printf رشته ورودی که در متغیر buffer هست را نشان می دهیم. سپس می توانیم با تابع ()send روی سوکت کلاینت بنویسیم. نخستین ورودی نام متغیری است که به سوکت سوی سرور اشاره می کند. دومین ورودی رشته یا متغیر رشته ای (در اینجا متغیر اشاره گر کاراکتری hello) است که می خوهیم به کلاینت فرستاده شود.کد کلاینتکد کلاینت نسبت به کد سرور، ساده تر و کوتاه تر است. در آن، همانند کد سرور، نخست باید یک سوکت بسازیم، زیرا کلاینت نیز باید یک نقطه پایانی برای فرستادن به و دریافت از نقطه دیگر داشته باشد. در ادامه کد کلاینت از همان سایتی که در بالا گفتم را توضیح می دهم ولی بخش هایی که از دید کد نویسی با کد سرور همسان هستند را نخواهم گفت.در آغاز دو متغیر به نام sock با مقدار پیش فرض صفر و valread از نوع int ساخته ایم. متغیر sock سپس برای برآیند تابع ()socket و valread برای نگهداری برآیند تابع ()read به کار می روند. متغیر دیگر ser_addr است که نمونه ای از ساختار struct sockaddr_in است که قرار است نشانی IP و شماره درگاه سرور را در کلاینت نشان دهد. در پایان دو متغیر hello و buffer که کاربردی همانند کد سرور دارند. در خط های ۲۱ و ۲۲ شکل زیر می توانید ببینید که عضوهای این سوکت مقداردهی شده اند.در خط ۱۸ می بینید که برای بیرون آمدن از برنامه در صورت بروز خطا، از دستور return -1 کمک گرفته شده است. این همسان با (exit(EXIT_FAILURE است، زیرا EXIT_FAILURE نیز شماره ای صحیح و منفی است.سپس تابع ()inet_pton برای تبدیل رشته نشانی IP (در اینجا 127.0.0.1) به بایت دودویی شبکه به کار گرفته می شود. سپس باید به کمک تابع ()connect به سرور (سوکت سرور) وصل شویم. ورودی یکم این تابع، نام متغیری است که سوکت کلاینت را نگه می دارد که در اینجا sock نام دارد. ورودی دوم یک تبدیل (Cast) از ساختار struct sockaddr_in به struct sockaddr است. در واقع ورودی دوم سوکت سرور را Cast می کند. اگر برآیند انجام ()connect کوچکتر از صفر باشد، پس خطایی رخ داده است. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%BE%D9%86%D8%AC%D9%85-ephuzqarrm9c سپس باید یک پیغام یا داده به سرور فرستاده شود که این کار بدست تابع ()send انجام می شود. پس از فرستادن پیغام به سرور، کلاینت منتظر پاسخ می ماند که این پاسخ به کمک تابع ()read از روی سوکت خوانده می شود.بنابراینکلاینت آغاز کننده ارتباط است و به سوکت شبکه وصل می شود.کلاینت نخست داده می فرستد و سپس در انتظار پاسخ ی ماند.سرور نخست پیغامی را می گیرد و سپس پاسخی را می فرستد.در سوی کلاینت باید ویژگی های سوکت شبکه را برای اتصال به آن داشته باشیم.شاد و پیروز و تندست باشید.</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 18 Mar 2020 14:47:44 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش پنجم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D9%BE%D9%86%D8%AC%D9%85-ephuzqarrm9c</link>
                <description>در این نوشته می خواهیم برخی نکته ها و تابع هایی که در برنامه نویسی سوکت نیاز هستند را به شما بگویم تا در نوشته های دیگر از پیش با آنها آشنا باشید. جدول زیر فهرستی از گونه های کاربردی در برنامه نویسی سی و سوکت نویسی را نشان می دهد. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt Data Typesاندازه ساختار سوکتبرای نمونه sa_family_t آدرس فامیلی سوکت مانند AF_INET یا AF_INET6 را نگهداری می کند که در واقع شماره های صحیحی هستند که به ریخت ماکرو شناسانده شده اند. socklen_t نیز یک گونه است که اندازه یک سوکت یا اندازه یک ساختار سوکت را نگهداری می کند. اندازه هر گونه داده مانند int یا struct ها را به کمک تابع ()sizeof بدست می آوریم.ساختار struct sockaddr_in دارای عضوهای گوناگونی از گونه ها است که هر یک اندازه ویژه خودش را دارد. برای نمونه عضو sin_addr که از گونه in_port_t است، اندازه اش ۱۶ بیت یا دو بایت است، زیرا in_port_t گونه ای صحیح بی علامت ۱۶ بیتی است. اندازه یک ساختار در زبان سی برابر با مجموع  اندازه همه عضوهای آن است. توجه کنید خود عضو sin_addr نمونه ای از یک ساختار دیگر به نام struct in_addr است، پس اندازه خود sin_addr برابر با اندازه همه عضوهای ساختار struct in_addr است که با اندازه دیگر عضوها جمع می شود.دیگر تابع های تبدیل در سوکت نویسیدر نوشته های پیشین درباره چهار تابع برای تبدیل آدرس و شماره پورت به بایت شبکه گفته ام و در اینجا یک دسته دیگر از تابع هایی که برای تبدیل آدرس های IP (نسخه ۴ یا ۶) به بایت های شبکه به کار می روند. این سه تابع در arpa/in.h شناسانده شده اند.تابع ()inet_aton یک رشته از کاراکترهای سی که یک آدرس IP را نشان می دهد را به بایت های دودویی شبکه تبدیل می کند. اگر آدرس معتبر و درست باشد، این تابع مقداری غیر صفر را برگشت می دهد وگرنه صفر برگشت داده خواهد شد.int inet_aton(const char *cp, struct in_addr *inp)در کد بالا که از رهنمای man inet_aton برداشته شده است، نمونه ای از کاربرد آن نشان داده شده است. نخست یک نمونه از ساختار struct addr_in ساخته ایم، زیرا دومین ورودی ()inet_aton یک گونه از struct in_addr است. در خط ۱۵ می بینید که آدرس متغیر addr دمین ورودی تابع است.نخستین ورودی تابع یک رشته است که آدرس IP (نسخه ۴) را مشخص می کند که باید به بایت های شبکه تبدیل شده و در متغیری که آدرس آن به دومین ورودی فرستاده شد، ذخیره شود. بنابراین دومین ورودی، فراخوانی یک متغیر با ارجاع (Call by Reference) است.در کد بالا نخست از خط فرمان یک ورودی خوانده می شود و سپس این ورودی به عنوان نخستین عنصر با اندیس صفر در آرایه رشته []argv نگهداری می شود. سپس این ورودی که یک رشته برابر با IP مانند 192.168.1.100 است به ورودی یکم فرستاده می شود.بنابراین رشته ای مانند 192.168.100 که قابل خواندن برای کاربران است به بایت های دودویی قابل استفاده در ماشین و شبکه تبدیل می شوند. توجه کنید که اگر آدرس IP معتبر باشد، برآیند تابع شماره ای غیر صفر است وگرنه پیغام خط ۱۷ نشان داده می شود و برنامه با نادرستی و بدست تابع ()exit پایان می یابد.تابع دیگر ()inet_ntoa است که در خط ۲۱ فراخوانی شده است و کاربردی وارونه ()inet_aton دارد. توجه کنید که ()inet_aton برای تبدیل رشته اسکی a به بایت شبکه n دارد ولی ()inet_ntoa برای تبدیل بایت شبکه n به رشته اسکی a قابل خوانده شدن بدست کاربران به کار می رود.char *inet_ntoa(struct in_addr in)توجه کنید ()inet_ntoa تنها یک ورودی دارد که آن نام متغیری از struct in_addr است و فراخوانی در ()inet_ntoa فراخوانی با مقدار (Call by Value) است. همچنین تابع ()inet_ntoa یک رشته از کاراکترها (* char) را برگشت می دهد که همان نشانی IP قابل خوانده شدن توسط کاربران است. تابع دیگر ()inet_addr است که یک ورودی رشته از کاراکترها دریافت کرده و سپس یک گونه از in_addr_t را برگشت می دهد.in_addr_t inet_addr(const char *cp);تابع دیگر ()inet_pton است که یک نشانی IPv4 یا IPv6 را از رشته ای به کد دودویی تبدیل می کند. این تابع سه ورودی دریافت می کند. نخستین ورودی یک آدرس فامیلی AF_INET یا AF_INET6 است. دومین ورودی یک رشته است که آدرس مبدا مانند 192.168.1.100 در IPv4 را مشخص می کند. سومین ورودی یک اشاره گر void است که آدرس دومین ورودی تبدیل شده در فامیلی آدرس نخستین ورودی در آن نگهداری می شود.int inet_pton(int af, const char *src, void *dst)در کد زیر نمونه ای از تبدیل آدرس های IPv4 و IPv6 به بایت های شبکه نشان داده شده است. نخست یک متغیر به نام buf و به اندازه یک ساختار struct in6_addr تعریف کرده ایم. توجه کنید ساختارهای in_addr و in6_addr به ترتیب IPv4 و IPv6 را نشان می دهند.در دنباله دو متغیر domain و s از گونه int و یک آرایه از کاراکترها به اندازه INET6_ADDRSTRLEN را ساخته ایم. سپس در شرط خط های ۱۲ تا ۱۶ بررسی می شود که آیا ورودی پارامترهای ورودی کمتر از سه تا نباشد. توجه کنید زمانی که می خواهیم با argc و argv ورودی از خط فرمان دریافت کنیم، argc به تعداد پارامترهای ورودی اشاره دارد که نخستین آنها نام برنامه و دیگر ورودی ها پارامترهایی هستند که در برنامه استفاده می شوند یا بر روند اجرای برنامه تاثیر می گذارند. بنابراین [0]argv به نخستین پارامتر ورودی۷ یعنی نام برنامه اجرایی اشاره دارد.برنامه بدین صورت است که باید یکی از آرگومان های i4 یا i6 که در ورودی و پس از نام برنامه مشخص شده باشد که از طریق [1]argv مشخص می شود. اگر پارامتر دوم i4 باشد، پس آدرس فامیلی AF_INET و اگر i6 باشد پس AF_INET6 خواهد بود.از تابع ()strcmp برای سنجش اندیس دوم argv با یکی از دو مقدار رشته i4 یا i6 استفاده شده است. به هر حال اگر دو رشته فرستاده شده به ()strcmp یکسان باشند، پس مقدار صفر برگشت داده می شود. توجه کنید نتیجه خط ۱۸ که یا AF_INET یا AF_INET6 است، در متغیر domain نگهداری می شود که سپس این متغیر نخستین ورودی تابع ()inet_pton خواهد بود.دومین ورودی تابع، سومین پارامتر ورودی از خط فرمان است که در [2]argv نگهداری می شود. سومین پارامتر ورودی نیز که نتیجه اجرای تابع در آن ریخته می شود، متغیر buf است. متغیر s برآیند تابع ()inet_pton است. تابع ()inet_pton هم برای IPv4 و هم برای IPv6 به کار می رود. تابع دیگر ()inet_ntop است که کاربردی وارونه ()inet_pton دارد.const char *inet_ntop (int family, cost void *addrptr, char *strptr, size_t len)در فایل netinet/in.h دو کاکرو به نام های INET_ADDRSTRLEN با مقدار ۱۶ و INET_ADDRSTRLEN با مقدار ۶۴ شناسانده شده اند که به ترتیب اندازه رشته (STRLEN) برای آدرس (ADDR) نسخه ۴ و ۶ را نشان می دهند. در واقع با رشته ای ۱۶ بیتی می توانیم IPv4 و با رشته ای ۴۶ بیتی می توانیم IPv6 را نشان دهیم.این اندازه ها با حساب یک بیت برای کاراکتر پایانی رشته ها در سی، یعنی 0\ یا Terminate Character حساب شده اند. به هر رو، اگر اندازه تعیین شده (در اینجا برای متغیر buf) کم باشد، یک اشاره گر تهی (Null Pointer) برگشت داده می شود، از این رو در زمان تعریف آرایه buf بیشترین مقدار را صرف نظر از IPv4 یا IPv6 در نظر گرفته شد است.شاد و پیروز و تندرست باشید.</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 18 Mar 2020 14:02:24 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش چهارم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DA%86%D9%87%D8%A7%D8%B1%D9%85-fi6jlgdjlwjt</link>
                <description>در دنباله سری آموزش های آشنایی با سوکت های شبکه در سی و لینوکس، در این نوشته می خواهم درباره برخی از تابع هایی گفتگو کنم که برای تبدیل نشانی های IP به کار می روند. کاربرد این تابع برای تبدیل یک نشانی IP اَسکی و قابل خوانده شدن توسط ما به ریخت بایتهای دودویی است که توسط ماشین قابل درک شدن هستند.برای نمونه نشانی 192.168.1.100 یا نشانی - 0:0:0:0:0ffff:c0a8:164 برای ما قابل خواندن و درک شدن است ولی ماشین که می خواهد به کمک لایه های TCP/IP بسته شبکه (Network Packet) را آماده کند و در پایان بر روی اینترنت قرار داده و به به ماشین دیگر بفرستند، نیاز دارد تا بایت های دودویی صفر و یک را داشته باشد. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj  https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig ترتیب بایت شبکهدر رایانه ها (چه دسکتاپ، سرور،موبایل یا هر ابزار دیگری) دو شیوه Little Endian و Big Endian برای ذخیره سازی بایت ها درون حافظه و دیسک ها هست. برای نمونه در نگهداری 56a7 نخست بایت های 56 و سپس بایت های a7 نگهداری می شوند که این شیوه Big Endian است.ولی بیشتر سیستم های عامل مانند لینوکس، ویندوز و مکینتاش (و شاید همه BSD ها) شیوه Little Endian را به کار می برند به گونه ای که نخست بایت های a7 و سپس 56 نگهداری می شوند. سیستم عامل سولاریس شیوه Big Endian را به کار برده است. https://virgool.io/@linux_internals/%D9%85%D9%81%D8%A7%D9%87%DB%8C%D9%85-little-endian-%D9%88-big-endian-rt5c3ailish0 بنابراین رایانه ها یک شیوه یکپارچه و همگانی برای نگهداری بایت ها را به کار نمی برند و از این برای آنکه رایانه ها و سیستم عامل های گوناگون بتوانند بر روی اینترنت و شبکه با یکدیگر در هم کنشی (تعامل) باشند، پس پروتکل های اینترنتی باید یک رویکرد یکپارچه و همگانی برای ترتیب بایت ها را به کار ببرند، زیرا قاعدتا نبودن این شیوه یکپارچه، باعث می شود در سوی دیگر، داده نادرست تفسیر شود. این شیوه یکپارچه برای ترتیب بایت های فرستاده شده روی شبکه را ترتیب بایت شبکه (Network Byte Order) می گویند.بنابراین زمانی که می خواهیم یک سوکت شبکه را بسازیم، می بایست که اطمینان داشته باشیم که داده های درون عضوهای sin_addr و sin_port از ساختار struct sockaddr_in برای IPv4 و struct coakaddr_in6 برای IPv6 ترتیب بایت شبکه را داشته باشند. برای براوردن این، دو دسته از تابع ها فراهم شده است.تابع هایی که نشانی هاست (IP) را به ترتیب بایت شبکه تبدیل می کنند که دو تابع ()htons و ()htonl در این دسته هستند.تابع هایی که ترتیب بایت شبکه را نشانی هاست (IP) تبدیل می کنند که دو تابع ()ntphs و ()ntohl در این دسته هستند.Network Byte Orderبنابراین دو دسته تابع با نام هایی به ریخت H-to-N که برای تبدیل نشانی های IP به جریان بایت های دودویی شبکه و وارونه آن، N-to-H هستند که جریان بایت های دودویی شبکه را به نشانی های IP قابل خوانده شده تبدیل می کنند. این چهار تابع به گونه ماکروها در فایل سرآیند arpa/inet.h شناسانده شده اند و از این رو برای به کارگیری آنها در فایل سی باید سرآیند arpa/inet.h را include# کنیم.همچنین این تابع همگی به دو دسته short (پایان نام s) و long (پایان نام l) دسته بندی می شوند. unsigned short گونه ۱۶ بیتی (۲ بایتی) و unsigned long گونه ۳۲ بیتی (۴ بایتی) است. در کد سی زیر می توانیم بررسی کنیم سیستم عاملی که کد درون آن انجام شده Big Endian یا Little Endian است.نمونه کد سی برای تشخیص سیستم Endianنخست در خط های ۳ و ۴ دو ماکر به نام های BIG_ENDIAN و LITTLE_ENDIAN با مقدارهای 0 و 1 نوشته شده است. سپس یک تابع به نام ()TestByteOrder که مقداری int را برگشت می دهد را نوشته ایم. درون تابع نخست یک متغیر short int به نام word با مقدار 0x0001 شناسانده ایم و در دنباله این مقدار int را به رشته از کاراکترها تبدیل (Cast) کرده ایم که برآیند در متغیری به نام b نگهداری می شود.درون عبارت پیش روی return که همانند if..else است، بررسی می کنیم که آیا عنصر نخست درون رشته b برابر با شماره ای است که در ماکرو BIG_ENDIAN نگهداری می شود یا وگرنه برابر با مقداری است که در ماکرو LITTLE_ENDIAN نگهداری می شود.اگر سیستم عامل از Big Endian پشتیبانی می کند پس بایت 00 شماره 0x0001 باید نخست نگهداری شود که برابر با مقدار 0 است که در ماکرو  BIG_ENDIAN نگهداری می شود وگرنه اگر از LITTLE_ENDIAN پشتیبانی کند، پس بایت 01 نخست نگهداری می شود که برابر با مقدار 1 است که در ماکرو  LITTLE_ENDIAN نگهداری می شود.Linux Support Little Endianکد زیر نمونه ای ساخت سوکت با ()socket و چگونگی مقداردهی درست عضوهای ساختار struct sockaddr_in را نشان می دهد. نخست دو متغیر int به نام port و ip با مقدارهای 9090 و INADDR_ANY را نوشته ایم. INADDR_ANY یک ماکرو است که در فایل سرآیند netinet/in.h شناسانده شده است و به نشانی 0.0.0.0 اشاره دارد.در IPv4 نشانی های ویژه ای هستند، مانند 127.0.0.1 که نشانی Loop Back یا نشانی به ماشین محلی یا لوکال هاست است. نشانی دیگر، 0.0.0.0 است که در واقع زمانی که بخواهیم به همه کارت های شبکه اشاره کنیم، می توانیم  0.0.0.0 را به کار ببریم.گاهی بر روی سرور چندین اینترفیس شبکه است و برای اینکه سوکت را به گونه ای بسازیم که بتواند بر روی شمار پورت و بر روی همه این آدرس ها گوش دهد، پس می توانیم جای تک تک آدرس های IP، نشانی 0.0.0.0 را به کار ببریم که در زبان سی ماکرو INADDR_ANY که int هست به این نشانی اشاره می کند.سپس یک سوکت UDP ساخته ایم زیرا که دومین ورودی SOCK_DRAM است و فامیلی آدرس آن IPv4 است، زیرا که ورودی یکم آن AF_INET است. سپس یک نمونه از ساختار sockaddr_in ساخته ایم و همانگونه که پیش از این گفته شد، باید با متدهای H-to-N شماره پورت و نشانی IP را ابه بایت شبکه تبدیل کنیم.htons() - htonl()شماره های پورت ۱۶ بیتی یا ۲ بایتی و دربازه شماره صفر تا ۶۵۵۳۵ هستند، پس ()htons را به کار برده ایم و چون شمارهای IPv4 برابر با ۳۲ بیت یا ۴ بایت هستند، پس ()htonl را به کار برده ایم. آنچه که در کد بالا گفته شد، یک نمایش از چگونگی ساخت سوکت است که با فراخوانی متد ()socket و سپس ساخت یک نمونه از ساختار struct sockaddr_in برای IPv4 انجام می شود.در کد بالا فرض بر نوشتن سوکت سرور است ولی همه چیز را نشان نمی دهد. در دنباله کد باید آدرس سوکتی IPv4 که در برگیرنده شماره پورت server_socket.sin_port و نشانی IP یعنی server_socket.sin_addr.s_addr را باید پس از این به سوکتی که فایل توصیفگر آن را ساخته ایم انقیاد (Bind) کنیم که این کار توسط تابع ()bind انجام می شود. در واقع با ()bind است که می گویم سوکت ساخته و نگهداری شده در (اینجا) متغیر server_socket_fd بر روی کدام نشانی (ها) و شماره پورت گوش دهد.شاد و پیروز و تندرست باشید.</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Fri, 13 Mar 2020 15:06:57 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش سوم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%B3%D9%88%D9%85-lb8d7ce5sqig</link>
                <description>در بخش های پیشین درباره سوکت های اینترنت (Internet Socket) و ساختارهای درون هسته لینوکس برای نمایش یک سوکت گفتیم. در دنباله آموزش، در این نوشته می خواهیم با تابع ()socket و مفاهیمی همچون آدرس فامیلی (Address Family) و گونه های سوکت گفتگو کنیم.تابع ()socketدر هر دو سوی کلاینت و سرور، نخستین گام برای ساخت یک سوکت، فراخوانی و مقداردهی درست تابع ()socket است. بر پایه کد زیر، این تابع سه ورودی را دریافت می کنند که به ترتیب آدرس فامیلی، نوع سوکت و پروتکل را نشان می دهند. مقدار برگشتی این تابع نیز بر پایه آنچه که در بخش یکم گفتیم، یک شماره صحیح است که در واقع یک توصیفگر فایل (File Descriptor) به یک فایل سوکت باز شده است.int socket(int domain, int type, int protocol); https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm  https://virgool.io/linux-internals/آشنایی-با-سوکت-های-شبکه-در-سی-و-لینوکس-بخش-دوم-e4ku3bqi7tsj پارامتر domain آدرس فامیلی را مشخص می کند که می تواند یکی از چندین مورد باشد که سه مقدار AF_INET و AF_INET6 یا AF_RAW برخی از آنها هستند. چون می خواهیم سوکت هایی روی شبکه (اینترنت سوکت) را بسازیم، پس اگر نشانی IP به کار رفته IPv4 باشد، پس ورودی نخست AF_INET وگرنه برای IPv6 برابر با AF_INET6 است.آدرس فامیلی گونه یا فرمت آدرس ورودی را برای سوکت نشان می دهد. برای نمونه نشانی 192.168.1.100 یک IPv4 خصوصی (محلی) برای رایانه شما است و نشانی - 0:0:0:0:0ffff:c0a8:164 نسخه IPv6 آن است. بنابراین برای ارتباط ها بر پایه IPv4 باید از AF_INET و بر پایه IPv6 از AF_INET6 کمک بگیریم.پارامتر type گونه ارتباط میان دو سو را نشان می دهد که چون داریم درباره سوکت های اینترنت می گویم، پس ارتباط می تواند TCP یا UDP باشد. اگر می خواهیم ارتباط از نوع TCP باشد، پس باید مقدار SOCK_STREAM وگرنه برای UDP باید مقدار SOCK_DGRAM را به کار ببریم.پروتکل TCP یک پروتکل امن، پایدار و دو سویِ (دو طرفه - Two Way)، بر پایه اتصال (Connection Based) است در حالی که UDP بر پایه دیتاگرام (DGRAM = DataGRAM)، ناپایدار و بی اتصال (Connection Less) است.فهرستی فراگیر از همه گزینه ها برای آدرس فامیلی و نوع ارتباط را می توانید از اینجا بخوانید یا در لینوکس خود دستور man 2 socket را اجرا کنید.سومین ورودی که protocol نام دارد، برای ساخت سوکت های اینترنت TCP و UDP همیشه دارای مقدار صفر است. توجه کنید هر سه ورودی ()socket از گونه int هستند و در واقع AF_INET و AF_INET6 و SOCK_STREAM و SOCK_DGRAM و دیگر گزینه ها، همگی به یک شماره صحیح اشاره دارند. همگی این گزینه ها در فایل سرآیند sys/socket.h به ریخت ماکروهای سی (دستورهای define) همانند شکل زیر شناسانده شده اند.Socket Macrosبر پایه شکل بالا می توانید ببینید که AF_INET برابر با ۱ و AF_INET6 برابر با ۱۰ است و SOCK_STREAM و SOCK_DGRAM برابر با ۱ و ۲ هستند. کدهای زیر به ترتیب سوکت های TCP و UDP را ساخته اند و از این رو متغیر های tcp_socket و udp_socket به ترتیب دو توصیفگر فایل هستند که از این پس برای اشاره به سومت ها به کار رفته و به دیگر تابع های فرستاده می شوند.tcp_socket = socket(AF_INET, SOCK_STREAM, 0);udp_socket = socket(AF_INET, SOCK_DGRAM, 0);</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 11 Mar 2020 20:35:41 +0330</pubDate>
            </item>
                    <item>
                <title>آشنایی با سوکت های شبکه در سی و لینوکس - بخش دوم</title>
                <link>https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-e4ku3bqi7tsj</link>
                <description>در دنباله نوشته های برنامه نویسی و آشنایی با معماری شبکه در لینوکس، در دومین نوشته از دسته نوشته های آشنایی با سوکت های شبکه در سی و لینوکس، می خواهم کمی درباره پیاده سازی آدرس IP4 (یا IPv4) در هسته لینوکس بگویم.همانند دیگر مولفه های یک سیستم عامل مانند مدیریت فرآیندها، سیستم فایل، دیوایس های سخت افزای و دیگر مولفه ها، مولفه شبکه و زیر مولفه های آن درون هسته لینوکس پیاده سازی شده اند. هسته لینوکس بر پایه سی و تا اندازه ای اسمبلی (برای نمونه در بوت شدن هسته) نوشته شده است.ساختار ها یا Structure ها در هسته لینوکسسی زبانی رویه ای (بر پایه تابع ها) است و زمانی که شما هسته لینوکس را بررسی می کنید، بسیار با تابع ها، اشاره گرها و به ویژه ساختارها یا همان Structure ها بر می خورید. در واقع این ساختارها، نوع های داده ای هستند که در برنامه نویسی در سطح یا فضای کاربر، به کار گرفته می شوند.هر یک از این ساختارها درون یکی از فایل سرآیند هسته لینوکس پیاده سازی شده اند. برای نمونه، ساختاری که یک کاربر لاگین کرده را نشان می دهد، در فایل سرآیند pwd.h پیاده سازی شده است. توجه کنید که یک ساختار یا struct در سی، دارای عضوهایی است که از طریق نام آن ساختار در دسترس هستند. به عبارت دیگر، یک کاربر با یک struct و هر ویژگی آن کاربر نیز با یکی از عضوهای struct پیاده سازی شده است.ساختار آدرس سوکت عمومیبرنامه هایی که سوکت را به کار می برند، نیاز دارند تا این توانایی را داشته باشند که نشانی اینترنت (IP) و شماره درگاه (Port) را برای هسته لینوکس مشخص کنند. برای نمونه کلاینت باید نشانی و شماره درگاه از پیش مشخص شده روی سرور را باید در خود مشخص کند تا هسته از مقصد بسته (Packet) آگاه باشد.در کنار این، نیاز است تا آدرس به برنامه فرستاده شود. برای نمونه، در پیاده سازی یک همانند Caller Id در تلفن ها که شماره تماس گیرنده نشان داده می شود، سرور باید این توانایی را داشته باشد که نشانی هر کلاینتی که با او ارتباط برقرار می کند را بخواند.struct sockaddrشکل بالا ساختار struct sockaddr که ساختار آدرس سوکت عمومی (Generic Socket Address Structure) را نشان می دهد. این ساختار اطلاعات آدرس سوکت را برای بسیاری از نوع های سوکت نگهداری می کند.عضو sa_family که از نوع unsigned short است، سوکت آدرس فامیلی (Address Family) را نشان می دهد که در ادامه درباره آن گفته شده است. برای ساخت سوکت برای IPv4 باید آدرس فامیلی AF_INET و برای IPv6 باید AF_INET6 را به کار ببریم. اندازه sa_family دو بایت است زیرا اندازه فضای اشغالی برای unsigned short برابر با دو بایت است.توجه کنید متغیری که از نوع unsigned short باشد می تواند مقداری میان بازه صفر تا ۶۵۵۳۵ را دریافت کند.عضو دیگر sa_data است که به گونه یک رشته (آرایه ای از کاراکترها) به اندازه ۱۴ بایت شناسانده شده است. این عضو اطلاعاتی همچون نشانی IP و شماره درگاه مقصد را نگه می دارد. شماره پورت ها، شماره ای در بازه صفر تا ۶۵۵۳۵ استو می توان با ۲ بایت یا ۱۶ بیت نمایش داد و نشانی IPv4 نیز ۳۲ بیتی یا ۴ بایتی هستند.ساختار آدرس سوکتساختار آدرس سوکت (Socket Address Structure) یا SAS یکی از چندین struct درون هسته لینوکس هستند. توجه کنید دو سوکت برای IPv4 و IPv6 داریم و از این رو به ازای IPv4 و IPv6 ساختارهای جدای از هم برای سوکت ها پیاده سازی شده است. برای پیاده سازی یا نمایش یک سوکت IPv4 در هسته لینوکس، دو ساختار به نام های struct in_addr و struct sockaddr_in پیاده سازی شده است که در آنها in کوتاه شده Internet است، زیرا در کنار سوکت های شبکه که ارتباط میان دو فرآیند در دو سوی شبکه را فراهم می کنند، سوکت های دیگری نیز در لینوکس هستند.struct sockaddr_in - struct in_addr IPv4ساختار struct sockaddr_inاین ساختار دارای سه عضو به نام های sin_family از نوع sa_family_t و sin_port از نوع in_port_t و sin_addr از نوع ساختار دومی، یعنی struct in_addr است. اگر نوشته بخش یکم را به یاد داشته باشید، گفته شد که یک سوکت در برگیرنده یک دوتایی (IP, Port) است که در struct sockaddr_in می بینید که دو عضو sin_port و sin_addr به ترتیب به این دو اشاره دارند. https://virgool.io/linux-internals/%D8%A2%D8%B4%D9%86%D8%A7%DB%8C%DB%8C-%D8%A8%D8%A7-%D8%B3%D9%88%DA%A9%D8%AA-%D9%87%D8%A7%DB%8C-%D8%B4%D8%A8%DA%A9%D9%87-%D8%AF%D8%B1-%D8%B3%DB%8C-%D9%88-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A8%D8%AE%D8%B4-%DB%8C%DA%A9%D9%85-wbohvfgswvmm واژه sin کوتاه شده socket internet است.نوع sin_port به گونه in_port_t است که در واقع یک نوع تعریف شده در سی است که به نوع uint16_t یا Unsigned Integer 16 bit اشاره می کند. خود in_port_t در فایل سرآیند به نام netinet/in.h و uint16_t نیز در فایل سرآیند inttypes.h شناسانده شده است. در واقع uint16_t یک مقدار صحیح ۱۶ بیتی به علامت (مثبت) است که بیشترین مقدار آن برابر با ۶۵۵۳۵ است و چون in_port_t نیز به uint16_t اشاره دارد، پس می توان با آن یک شماره پورت از صفر تا بیشترین و بالاترین شماره، یعنی ۶۵۵۳۵ را نگهداری کرد.توجه کنید تعداد یا بازه شماره پورت ها از شماره صفر تا ۶۵۵۳۵ است که این برپایه استاندارد IEEE است.عضو دیگر، یعنی sin_len از نوع شماره صحیح بی علامت ۸ بیتی uint8_t است که به منظور پشتیبانی از BSD 4.3 به بعد به ساختار struct sockaddr_in افزوده شده است و هرگز استفاده و مقداردهی (تنظیم) نمی شود. اگر زمانی راهنمای man ip را در لینوکس خواندید، شاید این عضو در ساختار نوشته شده در راهنما نباشد و نخستین عضو sin_family باشد. آدرس فامیلی که در نوشته دیگری درباره آن خواهم گفت، برای IPv4 همیشه برابر با AF_INET خواهد بود.برای برنامه نویسی سوکت در لینوکس، تنها سه عضو sin_family و sin_port و sin_addr نیاز هستند.ساختار struct in_addrعضو دیگر sin_addr است که در واقع یک آدرس IPv4 را نشان می دهد. آدرس های IPv4 به صورت ۳۲ بیت مانند 192.168.1.100 یا 127.0.0.1 یا 8.8.8.8 هستند. sin_addr خودش از نوع ساختار دیگر یعنی struct in_addr است. همانگونه که می بینید خود struct in_addr دارای یک عضو به نام s_addr (یا socket address) است که از نوع in_addr_t است و in_addr_t خودش اشاره به نوع uint32_t دارد که یک نوع صحیح بی علامت ۳۲ یبتی است.شکل زیر ساختار struct sockaddr_in را نشان می دهد که در آن سه مولفه اصلی، یعنی sin_family و sin_port و sin_addr به ترتیب ۱ و ۲ و ۸ بایت یا ۸ و ۱۶ و ۳۲ بیت را به خود اختصاص می دهند. ۸ بیت دوم، با شماره مشخص شده ۱ و دو ۸ بیت شماره های ۲ و ۳ و چهار بیت شماره های ۴ تا ۷ به ترتیب برای این عضوها هستند.هر سه این ساختارها در لینوکس در فایل سرآیند intet/in.h شناسانده شده اند.در برنامه نویسی شبکه و سوکت ها، باید متغیری از گونه sockaddr_in بسازیم. یک اشاره گر به struct sockaddr_in را می توان به sockaddr تبدیل (Cast) کرد و وارونه این نیز شدنی است. از این رو در تابعی مانند ()connect که یک ورودی اشاره گر به struct sockaddr می خواهد، می توان اشاره گری از گونه struct sockaddr_in فرستاد.ساختارهای IPv6لینوکس از نسخه ۲.۲ از IPv6 پشتیبانی را آغاز کرده است و از این رو در ارتباط با آن، ساختارهای struct in6_addr و struct sockaddr_in6 فراهم شده اند. در کد زیر می توانید ببینید که یک سوکت IPv6 با ساختار struct sockaddr_in6 نشان داده می شود که همانند سوکت های IPV4 دارای یک نشانی IP و شماره پورت هستند.آدرس فامیلی برای IPv6 همیشه برابر با AF_INET6 خواهد بود.struct scokaddr_in6 - struct in6_addr IPv6در ساختار struct sockaddr_in6 دو عضو به نام های sin6_flowinfo و sin6_scope_id هست که در struct sockaddr_in برای IPv4 نیست. هر آدرس IPv6 دامنه (Scope) ویژه ای دارد که در آن شناسانده شده است. دامنه، یک منطقه توپولوژیکی است که، در آن می توان آدرس IPv6 را به عنوان شناسه ای منحصر (Unique Id) به یک اینترفیس شبکه یا گروهی ای از اینترفیس های شبکه به کار برد. IPv6 از گونه های گوناگونی به نام unicast و multicast و anycast پشتیبانی می کند.گونه Unicast برای آدرس دهی یک تک میزبان (Host)، گونه Multicast برای آدرس دهی یک گروه از میزبان ها و Anycast برای آدرس دهی نزدیکترین عضو یک گروه از هست که بر پایه راهنمای man ip6 در لینوکس پیاده سازی نشده است. شکل زیر این Scope ها و شناسه (ID) آنها را نشان می دهد.IPv6 Scope ID and Nameآموزش IPv6 بسیار گسترده و بیرون از درون مایه این نوشته است و نوشته های جداگانه ای را می خواهد، از این رو IPv6 را دیگر در این سری از آموزش های برنامه نویسی سوکت نخواهم گفت. در نوشته پَسین درباره Address Family و Socket Type ها خواهم گفت.شاد و پیروز و تندرست باشید</description>
                <category>برنامه نویسی و مفاهیم رایانه</category>
                <author>برنامه نویسی و مفاهیم رایانه</author>
                <pubDate>Wed, 11 Mar 2020 13:51:55 +0330</pubDate>
            </item>
            </channel>
</rss>