برنامه نویسی

مصرف API ها در C: راهنمای عملی برای توسعه دهندگان مدرن

Summarize this content to 400 words in Persian Lang
امروزه استفاده از API های وب یک روش رایج برای تبادل داده بین برنامه ها است. آموزش‌های مصرف API در زبان‌هایی مانند جاوا اسکریپت، پایتون یا PHP فراوان است، اما C – اغلب با برنامه‌نویسی در سطح سیستم مرتبط است – به ندرت برای این منظور در نظر گرفته می‌شود. با این حال، C کاملاً قادر به رسیدگی به درخواست‌های API است، و آن را به گزینه‌ای مناسب برای سناریوهایی مانند سیستم‌های Point of Sale (PoS)، دستگاه‌های IoT یا برنامه‌های تعبیه‌شده تبدیل می‌کند، جایی که C قبلاً برای کارایی و کنترل سطح پایین آن استفاده می‌شود.

این مقاله به بررسی نحوه مصرف APIها در C با استفاده از کتابخانه libcurl می پردازد. در پایان، متوجه خواهید شد که چگونه می توان داده ها را از API ها با استفاده از C واکشی و پردازش کرد، و چرا این رویکرد حتی در توسعه مدرن مرتبط است.

چرا از C برای مصرف API استفاده کنیم؟

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

عملکرد: C عملکرد بالا و حداقل سربار را ارائه می دهد و آن را برای محیط های با محدودیت منابع مانند دستگاه های IoT مناسب می کند.
کنترل: مدیریت حافظه مستقیم امکان بهینه سازی دقیق را به خصوص برای سیستم های تعبیه شده فراهم می کند.
قابلیت همکاری: کاربرد گسترده C به این معنی است که به خوبی با عملیات سطح سیستم، مانند کنترل سخت افزار، حسگرها یا سایر تجهیزات جانبی ادغام می شود.
طول عمر: برنامه های کاربردی ساخته شده در C اغلب طول عمر طولانی دارند، به ویژه در صنایعی مانند خرده فروشی یا تولید.

معرفی libcurl: ابزاری برای HTTP در C

برای مصرف APIها در C، libcurl بهترین کتابخانه است. این یک کتابخانه منبع باز، قابل حمل و دارای ویژگی های غنی برای رسیدگی به درخواست های شبکه از طریق HTTP، HTTPS، FTP و موارد دیگر است. پشتیبانی می کند:

ایجاد GET، POST و سایر درخواست های HTTP.
مدیریت هدرها و احراز هویت
پردازش پاسخ ها به طور موثر

مراحل اولیه برای مصرف API در C

بیایید روند مصرف یک API با استفاده از C را طی کنیم، با تمرکز بر یک مثال واقعی از واکشی داده‌های JSON.

راه اندازی و نصب

برای استفاده از libcurl باید آن را روی سیستم خود نصب کنید. برای اکثر توزیع های لینوکس، این کار را می توان با موارد زیر انجام داد:

sudo apt-get install libcurl4-openssl-dev

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در ویندوز، می توانید باینری های از پیش کامپایل شده را از وب سایت libcurl دانلود کنید: https://curl.se/download.html

در macOS اگر از Homebrew استفاده می کنید، می توانید آن را از طریق نصب کنید

brew install curl

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ساختار برنامه C خود را

یک برنامه ساده C برای واکشی داده ها از یک API شامل اجزای زیر است:

راه اندازی libcurl
پیکربندی درخواست API (URL، روش HTTP، هدرها و غیره).
دریافت و ذخیره پاسخ.
پاکسازی منابع

در اینجا یک نمونه برنامه برای واکشی داده های JSON از یک API عمومی آورده شده است:

#include
#include
#include
#include

// Struct to hold response data
struct Memory {
char *response;
size_t size;
};

// Callback function to handle the data received from the API
static size_t ResponseCallback(void *contents, size_t size, size_t nmemb, void *userp) {
size_t totalSize = size * nmemb;
struct Memory *mem = (struct Memory *)userp;

printf(“. %zu %zu\n”, size, nmemb);
char *ptr = realloc(mem->response, mem->size + totalSize + 1);
if (ptr == NULL) {
printf(“Not enough memory to allocate buffer.\n”);
return 0;
}

mem->response = ptr;
memcpy(&(mem->response[mem->size]), contents, totalSize);
mem->size += totalSize;
mem->response[mem->size] = ‘\0’;

return totalSize;
}

int main() {
CURL *curl;
CURLcode res;
struct Memory chunk;

chunk.response = malloc(1); // Initialize memory
chunk.size = 0; // No data yet

curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();

if (curl) {
// Set URL of the API endpoint
char access_token[] = “your-access-token”;
char slug[] = “home”;
char version[]= “draft”;
char url[256];
snprintf(url, sizeof(url), “https://api.storyblok.com/v2/cdn/stories/%s?version=%s&token=%s”, slug, version, access_token);

// Print the URL
printf(“URL: %s\n”, url);

// initializing libcurl

// setting the URL
curl_easy_setopt(curl, CURLOPT_URL, url );

// Follow redirect
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

// Set callback function to handle response data
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ResponseCallback);

// Pass the Memory struct to the callback function
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

// Perform the HTTP GET request
res = curl_easy_perform(curl);

// Check for errors
if (res != CURLE_OK) {
fprintf(stderr, “curl_easy_perform() failed: %s\n”, curl_easy_strerror(res));
} else {
printf(“Response data size: %zu\n”, chunk.size);
//printf(“Response data: \n%s\n”, chunk.response);
}

// Cleanup
curl_easy_cleanup(curl);
}

// Free allocated memory
free(chunk.response);

curl_global_cleanup();
return 0;
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مراحل اجرا

کد را در یک فایل ذخیره کنید، به عنوان مثال، get.c.با دستور زیر آن را کامپایل کنید:

gcc get.c -o get -lcurl

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برنامه کامپایل شده را اجرا کنید:

./get

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

درک مکانیسم پاسخ به تماس در پاسخ های HTTP با libcurl

هنگام کار با libcurl برای رسیدگی به پاسخ‌های HTTP در C، درک رفتار تابع callback مهم است. تابع callback که برای پردازش داده های پاسخ تعریف می کنید، مانند ResponseCallback تابع، ممکن است چندین بار برای یک پاسخ HTTP فراخوانی شود. در اینجا دلیل و نحوه کار این است.

چرا تماس برگشتی چندین بار فراخوانی می شود؟

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

این رفتار اجازه می دهد:

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

چگونه کار می کند؟هر بار که تکه‌ای از داده‌ها از سرور دریافت می‌شود، libcurl تابع تماس شما را فراخوانی می‌کند. اندازه هر قطعه به شرایط شبکه، اندازه بافر و منطق داخلی libcurl بستگی دارد.تماس برگشتی باید تکه ها را جمع کند و در نهایت پاسخ کامل را بازسازی کند.

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

سرور شروع به ارسال پاسخ می کند.
libcurl اولین تکه را دریافت می کند و callback را فراخوانی می کند.
پاسخ به تماس، تکه را پردازش یا ذخیره می کند.
libcurl قطعه بعدی را دریافت می کند و دوباره تماس را فراخوانی می کند.
این روند تا دریافت کل پاسخ ادامه می یابد.

توضیح گام به گام کد منبع برای ResponseCallback تابع

را ResponseCallback تابعی است که هنگام دریافت داده توسط libcurl فراخوانی می شود.

اعلامیه عملکرد

static size_t ResponseCallback(void *contents, size_t size, size_t nmemb, void *userp)

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

void *contents: این یک اشاره گر به داده های دریافت شده از سرور است. libcurl این بافر را فراهم می کند و آن را با داده هایی که دانلود می کند پر می کند.

size_t size و size_t nmemb: اندازه هر بلوک حافظه (اندازه) و تعداد بلوک ها (nmemb) را نشان می دهد. با هم، size * nmemb اندازه کل داده های دریافت شده در این قطعه را نشان می دهد.

void *userp: این یک اشاره گر تعریف شده توسط کاربر است که از طریق آن به تابع callback ارسال می شود curl_easy_setopt(curl, CURLOPT_WRITEDATA, …). در این مثال، این یک اشاره گر به یک شی struct Memory است که پاسخ کامل را ذخیره می کند.

اندازه کل داده ها را محاسبه کنید

size_t totalSize = size * nmemb;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این اندازه کل قطعه فعلی داده های دریافتی را با ضرب اندازه یک بلوک (اندازه) در تعداد بلوک ها (nmemb) محاسبه می کند.به عنوان مثال، اگر سرور 8 بلوک 256 بایتی را ارسال کند، totalSize 8 * 256 = 2048 بایت خواهد بود.

دسترسی به داده های کاربر (struct Memory)

struct Memory *mem = (struct Memory *)userp;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

را userp اشاره گر به a فرستاده می شود struct Memory *. این ساختار قبلاً در برنامه اصلی ارسال شده است و برای جمع آوری داده های دریافتی استفاده می شود.

را struct Memory به این صورت تعریف می شود:

struct Memory {
char *response;
size_t size;
};

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

response: رشته ای اختصاص داده شده به صورت پویا که داده های دانلود شده را ذخیره می کند.

size: اندازه فعلی رشته پاسخ.

تخصیص مجدد حافظه

char *ptr = realloc(mem->response, mem->size + totalSize + 1);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اندازه بافر پاسخ را برای قرار دادن قطعه داده جدید تغییر می دهد:

mem->size: اندازه فعلی بافر.

totalSize: اندازه تکه جدید.

+1: برای پایان دهنده تهی (\0) فاصله بگذارید تا آن را به یک رشته C معتبر تبدیل کنید.

realloc: به صورت پویا حافظه را برای بافر پاسخ تخصیص می دهد.

اگر تخصیص ناموفق باشد، realloc NULL را برمی گرداند و حافظه قدیمی معتبر باقی می ماند.

رسیدگی به خطاهای تخصیص حافظه

if (ptr == NULL) {
printf(“Not enough memory to allocate buffer.\n”);
return 0;
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر تخصیص حافظه ناموفق باشد (بنابراین ptr است NULL، یک پیغام خطا چاپ کنید و 0 را برگردانید. بازگشت 0 به libcurl سیگنال می دهد تا انتقال را لغو کند.

بافر را به روز کنید

mem->response = ptr;
memcpy(&(mem->response[mem->size]), contents, totalSize);

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

mem->response = ptr: حافظه تخصیص یافته جدید را به نشانگر پاسخ بازگردانید.

memcpy: تکه جدیدی از داده ها را از محتویات در بافر کپی کنید:

&(mem->response[mem->size]): مکانی در بافر که داده های جدید باید در آن اضافه شوند (پایان داده های فعلی).

contents: داده های دریافتی از سرور.

totalSize: اندازه داده برای کپی کردن.

اندازه کل را به روز کنید

mem->size += totalSize;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

تهی رشته پاسخ را خاتمه دهید

mem->response[mem->size] = ‘\0’;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

یک پایان دهنده تهی در انتهای بافر پاسخ اضافه کنید تا آن را به یک رشته C معتبر تبدیل کنید.این تضمین می‌کند که می‌توان پاسخ را به‌طور ایمن به‌عنوان یک رشته تهی معمولی در نظر گرفت.

اندازه کل را برگردانید

return totalSize;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

چه زمانی باید C را برای API ها انتخاب کرد

از C برای مصرف API استفاده کنید زمانی که:

مسائل مربوط به عملکرد: C برای برنامه های کاربردی حساس به سرعت ایده آل است.
یکپارچه سازی سیستم: شما باید درخواست های شبکه را با عملیات سخت افزاری (مثلاً واکشی داده ها برای یک سیستم PoS) ترکیب کنید.
سیستم های جاسازی شده: دستگاه های محدود به منابع از کارایی C بهره می برند.

کنجکاوی و اکتشاف: گاهی اوقات، شما صرفاً به این دلیل از C استفاده می کنید که از برنامه نویسی لذت می برید و می خواهید خود را با کاوش در یک زبان سطح پایین تر برای کارهایی که اغلب برای کارهای سطح بالاتر رزرو می شود، به چالش بکشید. این یک راه عالی برای عمیق‌تر کردن درک شما از نحوه عملکرد همه چیز در زیر کاپوت است!

نتیجه گیری

مصرف APIها در C ممکن است در دنیای برنامه نویسی سطح بالا امروزی غیر متعارف به نظر برسد، اما ابزار قدرتمندی برای سناریوهایی است که نیاز به عملکرد، کنترل و ادغام با عملیات سطح سیستم دارند. با استفاده از کتابخانه‌هایی مانند libcurl، توسعه‌دهندگان می‌توانند به راحتی درخواست‌های HTTP را در برنامه‌های C ادغام کنند و شکاف بین APIهای مدرن و برنامه‌نویسی سنتی در سطح سیستم را پر کنند.

با این دانش، می‌توانید برنامه‌های C بسازید که به طور یکپارچه با APIها تعامل داشته باشند و ثابت کنند که C حتی در گردش‌های کاری توسعه مدرن نیز مرتبط است.

امروزه استفاده از API های وب یک روش رایج برای تبادل داده بین برنامه ها است. آموزش‌های مصرف API در زبان‌هایی مانند جاوا اسکریپت، پایتون یا PHP فراوان است، اما C – اغلب با برنامه‌نویسی در سطح سیستم مرتبط است – به ندرت برای این منظور در نظر گرفته می‌شود. با این حال، C کاملاً قادر به رسیدگی به درخواست‌های API است، و آن را به گزینه‌ای مناسب برای سناریوهایی مانند سیستم‌های Point of Sale (PoS)، دستگاه‌های IoT یا برنامه‌های تعبیه‌شده تبدیل می‌کند، جایی که C قبلاً برای کارایی و کنترل سطح پایین آن استفاده می‌شود.

این مقاله به بررسی نحوه مصرف APIها در C با استفاده از کتابخانه libcurl می پردازد. در پایان، متوجه خواهید شد که چگونه می توان داده ها را از API ها با استفاده از C واکشی و پردازش کرد، و چرا این رویکرد حتی در توسعه مدرن مرتبط است.

چرا از C برای مصرف API استفاده کنیم؟

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

  • عملکرد: C عملکرد بالا و حداقل سربار را ارائه می دهد و آن را برای محیط های با محدودیت منابع مانند دستگاه های IoT مناسب می کند.
  • کنترل: مدیریت حافظه مستقیم امکان بهینه سازی دقیق را به خصوص برای سیستم های تعبیه شده فراهم می کند.
  • قابلیت همکاری: کاربرد گسترده C به این معنی است که به خوبی با عملیات سطح سیستم، مانند کنترل سخت افزار، حسگرها یا سایر تجهیزات جانبی ادغام می شود.
  • طول عمر: برنامه های کاربردی ساخته شده در C اغلب طول عمر طولانی دارند، به ویژه در صنایعی مانند خرده فروشی یا تولید.

معرفی libcurl: ابزاری برای HTTP در C

برای مصرف APIها در C، libcurl بهترین کتابخانه است. این یک کتابخانه منبع باز، قابل حمل و دارای ویژگی های غنی برای رسیدگی به درخواست های شبکه از طریق HTTP، HTTPS، FTP و موارد دیگر است. پشتیبانی می کند:

  • ایجاد GET، POST و سایر درخواست های HTTP.
  • مدیریت هدرها و احراز هویت
  • پردازش پاسخ ها به طور موثر

مراحل اولیه برای مصرف API در C

بیایید روند مصرف یک API با استفاده از C را طی کنیم، با تمرکز بر یک مثال واقعی از واکشی داده‌های JSON.

راه اندازی و نصب

برای استفاده از libcurl باید آن را روی سیستم خود نصب کنید. برای اکثر توزیع های لینوکس، این کار را می توان با موارد زیر انجام داد:

sudo apt-get install libcurl4-openssl-dev
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در ویندوز، می توانید باینری های از پیش کامپایل شده را از وب سایت libcurl دانلود کنید: https://curl.se/download.html

در macOS اگر از Homebrew استفاده می کنید، می توانید آن را از طریق نصب کنید

brew install curl
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ساختار برنامه C خود را

یک برنامه ساده C برای واکشی داده ها از یک API شامل اجزای زیر است:

  • راه اندازی libcurl
  • پیکربندی درخواست API (URL، روش HTTP، هدرها و غیره).
  • دریافت و ذخیره پاسخ.
  • پاکسازی منابع

در اینجا یک نمونه برنامه برای واکشی داده های JSON از یک API عمومی آورده شده است:

#include 
#include 
#include 
#include 

// Struct to hold response data
struct Memory {
    char *response;
    size_t size;
};

// Callback function to handle the data received from the API
static size_t ResponseCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t totalSize = size * nmemb;
    struct Memory *mem = (struct Memory *)userp;

    printf(". %zu %zu\n", size, nmemb);
    char *ptr = realloc(mem->response, mem->size + totalSize + 1);
    if (ptr == NULL) {
        printf("Not enough memory to allocate buffer.\n");
        return 0;
    }

    mem->response = ptr;
    memcpy(&(mem->response[mem->size]), contents, totalSize);
    mem->size += totalSize;
    mem->response[mem->size] = '\0';

    return totalSize;
}

int main() {
    CURL *curl;
    CURLcode res;
    struct Memory chunk;

    chunk.response = malloc(1);  // Initialize memory
    chunk.size = 0;             // No data yet

    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if (curl) {
        // Set URL of the API endpoint
        char access_token[] = "your-access-token";
        char slug[] = "home";
        char version[]= "draft";
        char url[256];
        snprintf(url, sizeof(url), "https://api.storyblok.com/v2/cdn/stories/%s?version=%s&token=%s", slug, version, access_token);

        // Print the URL
        printf("URL: %s\n", url);

        // initializing libcurl

        // setting the URL
        curl_easy_setopt(curl, CURLOPT_URL, url );

        // Follow redirect
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

        // Set callback function to handle response data
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, ResponseCallback);

        // Pass the Memory struct to the callback function
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

        // Perform the HTTP GET request
        res = curl_easy_perform(curl);

        // Check for errors
        if (res != CURLE_OK) {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        } else {
            printf("Response data size: %zu\n", chunk.size);
            //printf("Response data: \n%s\n", chunk.response);
        }

        // Cleanup
        curl_easy_cleanup(curl);
    }

    // Free allocated memory
    free(chunk.response);

    curl_global_cleanup();
    return 0;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مراحل اجرا

کد را در یک فایل ذخیره کنید، به عنوان مثال، get.c.
با دستور زیر آن را کامپایل کنید:

gcc get.c -o get -lcurl
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برنامه کامپایل شده را اجرا کنید:

./get
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

درک مکانیسم پاسخ به تماس در پاسخ های HTTP با libcurl

هنگام کار با libcurl برای رسیدگی به پاسخ‌های HTTP در C، درک رفتار تابع callback مهم است. تابع callback که برای پردازش داده های پاسخ تعریف می کنید، مانند ResponseCallback تابع، ممکن است چندین بار برای یک پاسخ HTTP فراخوانی شود. در اینجا دلیل و نحوه کار این است.

چرا تماس برگشتی چندین بار فراخوانی می شود؟

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

این رفتار اجازه می دهد:

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

چگونه کار می کند؟
هر بار که تکه‌ای از داده‌ها از سرور دریافت می‌شود، libcurl تابع تماس شما را فراخوانی می‌کند. اندازه هر قطعه به شرایط شبکه، اندازه بافر و منطق داخلی libcurl بستگی دارد.
تماس برگشتی باید تکه ها را جمع کند و در نهایت پاسخ کامل را بازسازی کند.

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

  1. سرور شروع به ارسال پاسخ می کند.
  2. libcurl اولین تکه را دریافت می کند و callback را فراخوانی می کند.
  3. پاسخ به تماس، تکه را پردازش یا ذخیره می کند.
  4. libcurl قطعه بعدی را دریافت می کند و دوباره تماس را فراخوانی می کند.
  5. این روند تا دریافت کل پاسخ ادامه می یابد.

توضیح گام به گام کد منبع برای ResponseCallback تابع

را ResponseCallback تابعی است که هنگام دریافت داده توسط libcurl فراخوانی می شود.

اعلامیه عملکرد

static size_t ResponseCallback(void *contents, size_t size, size_t nmemb, void *userp)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  • void *contents: این یک اشاره گر به داده های دریافت شده از سرور است. libcurl این بافر را فراهم می کند و آن را با داده هایی که دانلود می کند پر می کند.
  • size_t size و size_t nmemb: اندازه هر بلوک حافظه (اندازه) و تعداد بلوک ها (nmemb) را نشان می دهد. با هم، size * nmemb اندازه کل داده های دریافت شده در این قطعه را نشان می دهد.
  • void *userp: این یک اشاره گر تعریف شده توسط کاربر است که از طریق آن به تابع callback ارسال می شود curl_easy_setopt(curl, CURLOPT_WRITEDATA, ...). در این مثال، این یک اشاره گر به یک شی struct Memory است که پاسخ کامل را ذخیره می کند.

اندازه کل داده ها را محاسبه کنید

size_t totalSize = size * nmemb;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این اندازه کل قطعه فعلی داده های دریافتی را با ضرب اندازه یک بلوک (اندازه) در تعداد بلوک ها (nmemb) محاسبه می کند.
به عنوان مثال، اگر سرور 8 بلوک 256 بایتی را ارسال کند، totalSize 8 * 256 = 2048 بایت خواهد بود.

دسترسی به داده های کاربر (struct Memory)

struct Memory *mem = (struct Memory *)userp;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

را userp اشاره گر به a فرستاده می شود struct Memory *. این ساختار قبلاً در برنامه اصلی ارسال شده است و برای جمع آوری داده های دریافتی استفاده می شود.

را struct Memory به این صورت تعریف می شود:

struct Memory {
    char *response;
    size_t size;
};
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  • response: رشته ای اختصاص داده شده به صورت پویا که داده های دانلود شده را ذخیره می کند.
  • size: اندازه فعلی رشته پاسخ.

تخصیص مجدد حافظه

char *ptr = realloc(mem->response, mem->size + totalSize + 1);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اندازه بافر پاسخ را برای قرار دادن قطعه داده جدید تغییر می دهد:

  • mem->size: اندازه فعلی بافر.
  • totalSize: اندازه تکه جدید.
  • +1: برای پایان دهنده تهی (\0) فاصله بگذارید تا آن را به یک رشته C معتبر تبدیل کنید.
  • realloc: به صورت پویا حافظه را برای بافر پاسخ تخصیص می دهد.

اگر تخصیص ناموفق باشد، realloc NULL را برمی گرداند و حافظه قدیمی معتبر باقی می ماند.

رسیدگی به خطاهای تخصیص حافظه

if (ptr == NULL) {
    printf("Not enough memory to allocate buffer.\n");
    return 0;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر تخصیص حافظه ناموفق باشد (بنابراین ptr است NULL، یک پیغام خطا چاپ کنید و 0 را برگردانید. بازگشت 0 به libcurl سیگنال می دهد تا انتقال را لغو کند.

بافر را به روز کنید

mem->response = ptr;
memcpy(&(mem->response[mem->size]), contents, totalSize);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  • mem->response = ptr: حافظه تخصیص یافته جدید را به نشانگر پاسخ بازگردانید.
  • memcpy: تکه جدیدی از داده ها را از محتویات در بافر کپی کنید:

    • &(mem->response[mem->size]): مکانی در بافر که داده های جدید باید در آن اضافه شوند (پایان داده های فعلی).
    • contents: داده های دریافتی از سرور.
    • totalSize: اندازه داده برای کپی کردن.

اندازه کل را به روز کنید

mem->size += totalSize;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

تهی رشته پاسخ را خاتمه دهید

mem->response[mem->size] = '\0';
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

یک پایان دهنده تهی در انتهای بافر پاسخ اضافه کنید تا آن را به یک رشته C معتبر تبدیل کنید.
این تضمین می‌کند که می‌توان پاسخ را به‌طور ایمن به‌عنوان یک رشته تهی معمولی در نظر گرفت.

اندازه کل را برگردانید

return totalSize;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

چه زمانی باید C را برای API ها انتخاب کرد

از C برای مصرف API استفاده کنید زمانی که:

  • مسائل مربوط به عملکرد: C برای برنامه های کاربردی حساس به سرعت ایده آل است.
  • یکپارچه سازی سیستم: شما باید درخواست های شبکه را با عملیات سخت افزاری (مثلاً واکشی داده ها برای یک سیستم PoS) ترکیب کنید.
  • سیستم های جاسازی شده: دستگاه های محدود به منابع از کارایی C بهره می برند.
  • کنجکاوی و اکتشاف: گاهی اوقات، شما صرفاً به این دلیل از C استفاده می کنید که از برنامه نویسی لذت می برید و می خواهید خود را با کاوش در یک زبان سطح پایین تر برای کارهایی که اغلب برای کارهای سطح بالاتر رزرو می شود، به چالش بکشید. این یک راه عالی برای عمیق‌تر کردن درک شما از نحوه عملکرد همه چیز در زیر کاپوت است!

نتیجه گیری

مصرف APIها در C ممکن است در دنیای برنامه نویسی سطح بالا امروزی غیر متعارف به نظر برسد، اما ابزار قدرتمندی برای سناریوهایی است که نیاز به عملکرد، کنترل و ادغام با عملیات سطح سیستم دارند. با استفاده از کتابخانه‌هایی مانند libcurl، توسعه‌دهندگان می‌توانند به راحتی درخواست‌های HTTP را در برنامه‌های C ادغام کنند و شکاف بین APIهای مدرن و برنامه‌نویسی سنتی در سطح سیستم را پر کنند.

با این دانش، می‌توانید برنامه‌های C بسازید که به طور یکپارچه با APIها تعامل داشته باشند و ثابت کنند که C حتی در گردش‌های کاری توسعه مدرن نیز مرتبط است.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا