درس 12 : نوشتن بازیهای تحت شبکه با SDL_net قسمت سوم

قسمت 3 : ساخت یک سرور و یک کلاینت ساده

 

استفاده از TCP :

اگر شما یک رتباط مطمئن ولی کند می خواهید TCP نیاز شما را تامین می کند (البته این را بدانید که وقتی فایل

مثلا PDF یا ZIP یا ... دانلود می کنید شما از این پروتکل استفاده می کنید )  خصوصیت این ارتباط این است

که در آنور چک می کند که فایل سالم رسیده یا نه و این سرعت کار را پایین می آورد ولی UDP دقیقا عکس این

 خصوصیات را دارد و از این لحاظ به درد انتقال فیلم و صدا می خورد مثلا حذف شدن چند فرم از فیلم برای شما مهم نیست .

در ساخت ساده ترین برنامه کلاینت -  سرور ما  کارهای زیر را انجام می دهیم.

 

ابتدا ساخت قسمت سرور :

1.     اماده سازی کتابخانه SDL_net

2.     انتخاب کردن پورتی که سرور روی ان گوش بایستد.

3.     ساخت سوکتی برای سرور

4.     قبول کردن اتصال ( فرض کنید سرور صاحب خانه است و خونه اش 65536  تا در داره

 و هر در یک شماره دارد و جلوی هر در که بایستد با در های دیگر فاصله زیادی دارد در مرحله

      2 ما در را انتخاب می کنیم که انجا منتظر مهمان می شویم و در این مرحله ما باید  به مهمان ها اجازه ورود بدهیم )

 

5.     دریافت اطلاعات

6.     انجام دادن اعمالی با داده ها (مثلا نمایش انها )

7.     قطع ارتباط و خروج از برنامه

 

در قسمت کلاینت (مشتری {مهمان خودمان} ):

1.اماده کردن کتابخانه SDL_net

2. گرفتن ادرس سرور

3.ساختن یک سوکت

4.گرفتن اطلاعات از کاربر

5.فرستادن اطلاعات

6.قطع ارتباط و خروج

 

البته توجه کنید در این مثال سرور ما فقط یک کانکشن را قبول می کند

( با استفاده از thread ها می توان اتصالات زیادی را مدیریت کرد)

 

#include

#include

#include

 

#include "SDL_net.h"

 

int main(int argc, char **argv)

{

            TCPsocket sd, csd; /* Socket descriptor, Client socket descriptor */

            IPaddress ip, *remoteIP;

            int quit, quit2;

            char buffer[512];

            if (SDLNet_Init() < 0)

            {

                        fprintf(stderr, "SDLNet_Init: %s ", SDLNet_GetError());

                        exit(EXIT_FAILURE);

            }

در ابتدا ما متغییرها را تعریف می کنیم

Sd سوکت سرور ما برای انتقال اطلاعات است csd سوکت برای کلاینت هایی است که می ایند

ip ساختار ادرس سرور ماست و remoteIP هم ساختار ادرس کلاینت ماست

quit برای کل برنامه هست

quit2 هم برای این است که کلاینت کارش تمام شد دوباره سرور listen کند

Buffer هم نگه دارنده متنی است که کلاینت برای ما می فرستد.

            /* Resolving the host using NULL make network interface to listen */

            if (SDLNet_ResolveHost(&ip, NULL, 2000))

            {

                        fprintf(stderr, "SDLNet_ResolveHost: %s ", SDLNet_GetError());

                        exit(EXIT_FAILURE);

            }

 

در اینجا با تنظیم کردن پارامتر دوم به NULL و سوم به 2000 مشخص می کنیم

 که ساختار ip باید یک سرور باشد و بر روی پورت 2000 گوش بایستد.

            /* Open a connection with the IP provided (listen on the host's port) */

            if (!(sd = SDLNet_TCP_Open(&ip)))

            {

                        fprintf(stderr, "SDLNet_TCP_Open: %s ", SDLNet_GetError());

                        exit(EXIT_FAILURE);

            }

در اینجا سوکت سرور را با ادرس ip می سازد و شروع می کند به listen کردن روی پورت2000

            /* Wait a connection, send data and term */

            quit = 0;

            while (!quit)

            {

                        /* This check the sd if there is a pending connection.

                        * If there is one, accept that, and open a new socket for communicating */

                        if ((csd = SDLNet_TCP_Accept(sd)))

                        {

 

حلقه اصلی برنامه و پس از ان تابع SDLNet_TCP_Accept(sd) چک میکند که کلاینتی

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

                                    /* Now we can communicate with the client using csd socket

                                    * sd will remain opened waiting other connections */

 

                                    /* Get the remote address */

                                    if ((remoteIP = SDLNet_TCP_GetPeerAddress(csd)))

                                                /* Print the address, converting in the host format */

                                                printf("Host connected: %x %d ", SDLNet_Read32(&remoteIP->host), SDLNet_Read16(&remoteIP->port));

                                    else

                                                fprintf(stderr, "SDLNet_TCP_GetPeerAddress: %s ", SDLNet_GetError());

 

حال ما می توانیم با سوکت csd با کلاینب ارتباط برقرار کنیم

مامی توانیم با استفاده از تابع SDLNet_TCP_GetPeerAddress و دادن سوکت مورد نظر

 ساختار ادرس کلاینت را بگیریم که شامل IP->hostو IP->remoteIP است

quit2 = 0;

                                    while (!quit2)

                                    {

                                                if (SDLNet_TCP_Recv(csd, buffer, 512))

                                                {

                                                            printf("Client say: %s ", buffer);

 

                                                            if(strcmp(buffer, "exit") == 0)     /* Terminate this connection */

                                                            {

                                                                        quit2 = 1;

                                                                        printf("Terminate connection ");

                                                            }

                                                            if(strcmp(buffer, "quit") == 0)    /* Quit the program */

                                                            {

                                                                        quit2 = 1;

                                                                        quit = 1;

                                                                        printf("Quit program ");

                                                            }

                                                }

                                    }

 

                                    /* Close the client socket */

                                    SDLNet_TCP_Close(csd);

                        }

            }

 

            SDLNet_TCP_Close(sd);

            SDLNet_Quit();

 

            return EXIT_SUCCESS;

}

 

تابع SDLNet_TCP_Recv(csd,buffer,512) در صورتی که چیزی از کلاینت دریافت کند

 مقدار غیر صفر بر می گرداند و پارامتر اول که سوکت کلاینت است در buffer هم اطلاعات فرستاده

شده ذخیره می شود و پارامترسوم هم حداکثر مقدار اطلاعاتی است به بایت که باید دریافت کند.

و بعد از ان هم با printf داده فرستاده شده را نمایش می دهد.در صورت وارد کردن quit برنامه سرور بسته می شود

و اگر کلاینت کلمه exit را بفرستد سرور این کلاینت را رها کرده و دوباره به listening  می پردازد.

 

و حالا کد کلاینت :

#include

#include

#include

 

#include "SDL_net.h"

 

int main(int argc, char **argv)

{

            IPaddress ip;                        /* Server address */

            TCPsocket sd;                      /* Socket descriptor */

            int quit, len;

            char buffer[512];

 

            /* Simple parameter checking */

            if (argc < 3)

            {

                        fprintf(stderr, "Usage: %s host port ", argv[0]);

                        exit(EXIT_FAILURE);

            }

            if (SDLNet_Init() < 0)

            {

                        fprintf(stderr, "SDLNet_Init: %s ", SDLNet_GetError());

                        exit(EXIT_FAILURE);

            }

 

 

در اینجا ip ساختار آدرس سرور است و TCPsocket هم سوکتی است که ما با ان می خواهیم

 با سرور ارتباط برقرار کنیم quit برای کنترل خرج از برنامه است و len هم طول رشته ارصالی است

 و buffer هم رشته که می خواهیم بفرستیم. سپس چک می کنیم که کاربر حداقل دو پارامتر را وارد کرده

 باشد یکی ip سرور و دیگری پورت باز بر روی سرور است.

            /* Resolve the host we are connecting to */

            if (SDLNet_ResolveHost(&ip, argv[1], atoi(argv[2])))

            {

                        fprintf(stderr, "SDLNet_ResolveHost: %s ", SDLNet_GetError());

                        exit(EXIT_FAILURE);

            }

در اینجا هم ip و port سرور را به ساختار IPaddress تبدیل می کنیم.

            /* Open a connection with the IP provided (listen on the host's port) */

            if (!(sd = SDLNet_TCP_Open(&ip)))

            {

                        fprintf(stderr, "SDLNet_TCP_Open: %s ", SDLNet_GetError());

                        exit(EXIT_FAILURE);

            }

در اینجا هم با ساختار ip یک سوکت برای ارتباط با سرور می سازیم
 

            /* Send messages */

            quit = 0;

            while (!quit)

            {

                        printf("Write something: >");

                        scanf("%s", buffer);

 

                        len = strlen(buffer) + 1;

                        if (SDLNet_TCP_Send(sd, (void *)buffer, len) < len)

                        {

                                    fprintf(stderr, "SDLNet_TCP_Send: %s ", SDLNet_GetError());

                                    exit(EXIT_FAILURE);

                        }

 

                        if(strcmp(buffer, "exit") == 0)

                                    quit = 1;

                        if(strcmp(buffer, "quit") == 0)

                                    quit = 1;

            }

 

            SDLNet_TCP_Close(sd);

            SDLNet_Quit();

 

            return EXIT_SUCCESS;

}
در ابتدا با scanf یک رشته را می خواند سپس طول رشته را بدست می اورد و
 سپس با SDLNet_TCP_Send رشته را می فرستد
 و در صورت وارد کردن exit و quit از کلاینت خارج می شود.
شیشسی
شیب

 

نظرات 0 + ارسال نظر
برای نمایش آواتار خود در این وبلاگ در سایت Gravatar.com ثبت نام کنید. (راهنما)
ایمیل شما بعد از ثبت نمایش داده نخواهد شد