در توسینسو تدریس کنید

و

با دانش خود درآمد کسب کنید

آموزش برنامه نویسی C قسمت 26 : Socket Programming

سلام و وقت بخیر. در این جلسه درمورد مبحث مهم socket صحبت خواهیم کرد. معمولا در داخل یک سیستم یا بهتر بگوییم در داخل یک localhost، برای ارتباط میان 2 تا پروسه ( process )، سه تکنیک وجود دارد.

1- Pipes

2-Message queues

3-Shared memory

میتوان دسته بندی بیشتری هم کرد ولی موارد بالا، از همه کلاسیک تر و عام تر هستند. اما در شبکه چطور 2 تا پروسه با هم ارتباط برقرار میکنند؟؟ مثلا وقتی شما از کامپیوتر خود به یک وب سایت متصل میشوید، پروسه در حال اجرا درون کامپیوتر شما web browser و پروسه در حال اجرا در سرور مقصد، web server است. این دو پروسه از طریق یک تکنیک به نام Socket با یکدیگر ارتباط برقرار میکنند.

سوکت چیست؟

بنا بر تعریف، سوکت نقطه نهایی ارتباط بین ئو سیستم در یک شبکه است. یکم دقیق تر، سوکت به مجموع IP و Port درون یک سیستم گفته میشود. بنابراین در هر طرف ارتباط، یک سوکت وجود دارد که با سوکت دستگاه طرف مقابل ارتباط برقرار میکند.بطور کلی دو دسته ارتباط در بستر شبکه داریم:

1- ارتباط بر بستر مدل OSI

2- ارتباط بر بستر مدل TCP/IP

احتمالا میدونید که مدل OSI بیشتر جنبه آکادمیک و آموزشی دارد و فقط در کتاب های مرجع زیارتش میکنید و در عمل مدل TCP/IP زیرساخت ارتباطات شبکه ها است. سوکت را میتوان با بسیاری از زبان های برنامه نویسی تا اونجایی که من میدونم نوشت، مثل ++c و java و ... . اما در اینجا ما نوشتن یک سوکت خیلی ساده به زبان c را تمرین میکنیم.

پس اگر تا اینجا مطلب را دنبال کرده باشید میدانید که برای برقراری ارتباط، به دو طرف حداقل نیاز است که یکی سرویس دهنده ( سرور ) و یکی سرویس گیرنده ( کاربر ) باشد. یک فایل خالی جدید به نام server.c ایجاد کرده و کد های زیر را درون آن وارد کنید.

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h> 

int main(int argc, char *argv[])
{
	/*Variable*/
    int listenfd = 0, connfd = 0;
    struct sockaddr_in serv_addr; 

    char sendBuff[1025];
    time_t ticks; 

	/*Creat Socket*/
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&serv_addr, '0', sizeof(serv_addr));
    memset(sendBuff, '0', sizeof(sendBuff)); 

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(5000); 

	/*Call Bind*/
    bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 

	/*Listen*/
    listen(listenfd, 10); 

	/*Accept*/
    while(1)
    {
        connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); 

        ticks = time(NULL);
        snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
        write(connfd, sendBuff, strlen(sendBuff)); 

        close(connfd);
        sleep(1);
     }
}

کد بالا چکار میکند؟

1- تابع socket درون kernel یک سوکت بدون نام درست کرده و یک عدد int به عنوان socket descriptor برمیگرداند. این تابع domainfamily را به عنوان آرگومان اول میپذیرد. چون از IPv4 استفاده میکنیم، به عنوان Internet Family برای IPv4 از کلمه کلیدی AF_INET استفاده میکنیم. در آرگومان دوم این تابع مشخص میکنیم که از لایه انتقال مدل TCPIP استفاده کن. برای این آرگومان مهم است که مقداری که باریش مشخص میکنیم، خاصیت acknowledgement داشته باشد مثل TCP. ( اگه چیزایی که میگم رو متوجه نمیشید برید مباحث +network رو یه نگاه بندازید. ) آرگومان سوم هم معمولا صفر است تا kernel از پروتکل پیش فرض ارتباطی شی گراء یعنی TCP استفاده کند.

2- تابع bind جزئیاتی که در ساختار serv-addr وجود دارد را به سوکتی که در مرحله قبل ایجاد شد الحاق میکند. جزئیاتی که الحاق میشود شامل family/domain ، و interface ای که باید از آن گوش کند ( listen ) و پروتی که سرور روی آن گوش میدهد و منتظر درخواست کاربر است.

3- در تابع listen آرگومان دوم که عدد 10 گرفته یعنی اینکه سرور حداکثر 10 تا connection از طرف سوکت کاربر قبول میکند.

4- پس از اینکه تابع listen با موفقیت ایجاد شد، سوکت بصورت عملیاتی شروع به گوش دادن میکند.

5- هنگامی که تابع accept فراخوانی میشود، سرور وارد فاز sleep میشود و منتظر میماند تا درخواستی از سمت کاربر فرستاده شود. وقتی که درخواست کاربر به سرور رسید، three way TCP handshake انجام میشود (به مباحث +network مراجعه کنید) و socket descriptor را به عنوان سوکت کاربر برمیگرداند.

6- تابع accept در یک حلقه بی نهایت قرار دارد، پس سرور همیشه آماده بکار است. برای اینکه سرور منابع سیستم را یکباره اشغال نکند یک تاخیر 1 ثانیه ای گذاشتیم.

7- هنگامی که یک درخواست از طرف کاربر رسید، در سرور زمان و تاریخ محاسبه شده و از طریق descriptor که توسط تابع accept برگردانده میشود، درون سوکت ارتباطی با کاربر نوشته میشود و کاربر آنرا دریافت میکند.

حال یک فایل خالی دیگر با اسم client.c ایجاد کرده و کد های زیر را درون آن وارد کنید.

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h> 

int main(int argc, char *argv[])
{
    int sockfd = 0, n = 0;
    char recvBuff[1024];
    struct sockaddr_in serv_addr; 

    if(argc != 2)
    {
        printf("\n Usage: %s <ip of server> \n",argv[0]);
        return 1;
    } 

    memset(recvBuff, '0',sizeof(recvBuff));
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Error : Could not create socket \n");
        return 1;
    } 

    memset(&serv_addr, '0', sizeof(serv_addr)); 

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(5000); 

    if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
    {
        printf("\n inet_pton error occured\n");
        return 1;
    } 

    if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
       printf("\n Error : Connect Failed \n");
       return 1;
    } 

    while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
    {
        recvBuff[n] = 0;
        if(fputs(recvBuff, stdout) == EOF)
        {
            printf("\n Error : Fputs error\n");
        }
    } 

    if(n < 0)
    {
        printf("\n Read error \n");
    } 

    return 0;
}

حالا این کد چه میکند ؟

1- اینجا هم یک سوکت با تابع socket ایجاد میشود.

2- اطلاعاتی نظیر IP و پورت سرور در یک struct توسط تابع connect صدا زده میشود که قصد دارد با سوکت ایجاد شده با سرور ارتباط برقرار کند.

3- دقت کنید که در اینجا کاربر را ملزم به استفاده از یک پورت خاص برای ایجاد سوکت نکردیم، بلکه انتخاب پورت را به kernel واگذار کردیم. در حالی که پورتی که سرور با آن کار میکند باید مشخص باشد که معولا در سناریو های واقعی شماره پورت های زیر 1024 است مثل پورت 80 برای ارتباطات HTTP.

4- هنگامی که سوکت ایجاد شد، سرور دیتایی (در اینجا date + time ) را برای کاربر، از طریق سوکت ارتباطی برقرار شده میفرستد و کاربر به راحتی آنرا میخواند.

برای اجرای برنامه 2 تا ترمینال باز کنید. در یکی server.c را کامپایل و اجرا کرده و در دیگری client.c را کامپایل و اجرا کنید. به ابنصورت که هر دو کد را با gcc کامپایل کنید. سپس در ترمینالی که کد سرور را کامپایل کردید دستور server. را زده، خواهید دید که ترمینال را اشغال میکند و دستور دیگری نمیتوانید وارد کنید. سپس در ترمینالی که کد کاربر را کامپایل کردید دستور client. را با آرگومان IP سرور وارد کنید.

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

[root@CentOS6 c]# gcc -o server server.c
[root@CentOS6 c]# ./server

در ترمینال کاربر:

[root@CentOS6 c]# ./client 127.0.0.1
Sat Aug 13 19:37:52 2016
[root@CentOS6 c]# 

پایان قسمت بیست و ششم

نویسنده : سید محمد باقر موسوی

منبع : جزیره برنامه نویسی وب سایت توسینسو

هرگونه نشر و کپی برداری بدون ذکر منبع و نام نویسنده دارای اشکال اخلاقی است

#برنامه_نویسی_به_زبان_c #نوشتن_shell_script_در_لینوکس #زبان_برنامه_نویسی_c_در_لینوکس #برنامه_نویسی_c_در_محیط_لینوکس #برنامه_نویسی_به_زبان_c_در_لینوکس #آموزش_گام_به_گام_برنامه_نویسی_c #برنامه_نویسی_c_در_linux #آموزش_برنامه_نویسی_c_در_لینوکس
عنوان
1 آموزش برنامه نویسی C قسمت 1 : نصب محیط برنامه نویسی رایگان
2 آموزش برنامه نویسی C قسمت 2 : Hello World رایگان
3 آموزش برنامه نویسی C قسمت 3 : Data Types رایگان
4 آموزش برنامه نویسی C قسمت 4 : Data Types رایگان
5 آموزش برنامه نویسی C قسمت 5 : اشاره گر ها رایگان
6 آموزش برنامه نویسی C قسمت 6 : آرایه ها رایگان
7 آموزش برنامه نویسی C قسمت 7 : ساختار شرط IF رایگان
8 آموزش برنامه نویسی C قسمت 8 : حلقه for رایگان
9 آموزش برنامه نویسی C قسمت 9 : حلقه While رایگان
10 آموزش برنامه نویسی C قسمت 10 : Struct رایگان
11 آموزش برنامه نویسی C قسمت 11 : تابع دریافت ورودی scanf رایگان
12 آموزش برنامه نویسی C قسمت 12 : فایل های متنی و باینری رایگان
13 آموزش برنامه نویسی C قسمت 13 : توابع رایگان
14 آموزش برنامه نویسی C قسمت 14 : توابع اشاره گر رایگان
15 آموزش برنامه نویسی C قسمت 15 : argc argv رایگان
16 آموزش برنامه نویسی C قسمت 16 : Multiple Source Files رایگان
17 آموزش برنامه نویسی C قسمت 17 : String Functions & Operations رایگان
18 آموزش برنامه نویسی C قسمت 18 : Char Pointers VS Array Char رایگان
19 آموزش برنامه نویسی C قسمت 19 : Binary & Unary Operations رایگان
20 آموزش برنامه نویسی C قسمت 20 : Type Casting رایگان
21 آموزش برنامه نویسی C قسمت 21 : readdir & opendir functions رایگان
22 آموزش برنامه نویسی C قسمت 22 : Fork Function رایگان
23 آموزش برنامه نویسی C قسمت 23 : Thread رایگان
24 آموزش برنامه نویسی C قسمت 24 : Switch Case Statement رایگان
25 آموزش برنامه نویسی C قسمت 25 : qsort رایگان
26 آموزش برنامه نویسی C قسمت 26 : Socket Programming رایگان
27 آموزش برنامه نویسی C قسمت 27 : لیست پیوندی (Linked List) رایگان
زمان و قیمت کل 0″ 0
0 نظر

هیچ نظری ارسال نشده است! اولین نظر برای این مطلب را شما ارسال کنید...

نظر شما
برای ارسال نظر باید وارد شوید.
از سرتاسر توسینسو
تنظیمات حریم خصوصی
تائید صرفنظر
×

تو می تونی بهترین نتیجه رو تضمینی با بهترین های ایران بدست بیاری ، پس مقایسه کن و بعد خرید کن : فقط توی جشنواره تابستانه می تونی امروز ارزونتر از فردا خرید کنی ....