>  기사  >  백엔드 개발  >  C에서 API 사용: 현대 개발자를 위한 실용적인 가이드

C에서 API 사용: 현대 개발자를 위한 실용적인 가이드

Patricia Arquette
Patricia Arquette원래의
2024-11-24 08:10:10404검색

Consuming APIs in C: a practical guide for modern developers

오늘날 웹 API를 사용하는 것은 애플리케이션 간 데이터 교환을 위한 일반적인 관행입니다. JavaScript, Python 또는 PHP와 같은 언어로 API를 사용하는 방법에 대한 자습서는 많지만 시스템 수준 프로그래밍과 관련된 C는 이러한 목적으로 거의 고려되지 않습니다. 그러나 C는 API 요청을 완벽하게 처리할 수 있으므로 PoS(Point of Sale) 시스템, IoT 장치 또는 임베디드 애플리케이션과 같은 시나리오에서 실행 가능한 선택이 됩니다. 여기서 C는 효율성과 낮은 수준의 제어를 위해 이미 사용되고 있습니다.

이 기사에서는 libcurl 라이브러리를 활용하여 C에서 API를 사용하는 방법을 살펴봅니다. 마지막에는 C를 사용하여 API에서 데이터를 가져오고 처리하는 방법과 이 접근 방식이 현대 개발에도 적합한 이유를 이해하게 됩니다.

API 소비에 C를 사용하는 이유는 무엇입니까?

고급 언어가 웹 개발을 지배하지만 C는 여전히 특정 사용 사례에서 API를 사용하기 위한 실용적인 선택입니다.

  • 성능: C는 고성능과 최소한의 오버헤드를 제공하므로 IoT 기기와 같이 리소스가 제한된 환경에 적합합니다.
  • 제어: 직접 메모리 관리를 통해 특히 임베디드 시스템의 경우 미세 조정된 최적화가 가능합니다.
  • 상호 운용성: C가 널리 사용된다는 것은 하드웨어, 센서 또는 기타 주변 장치 제어와 같은 시스템 수준 작업과 잘 통합된다는 것을 의미합니다.
  • 장수명: C로 구축된 애플리케이션은 특히 소매나 제조와 같은 산업에서 수명이 긴 경우가 많습니다.

libcurl 소개: C의 HTTP용 도구

C에서 API를 사용하려면 libcurl이 적합한 라이브러리입니다. HTTP, HTTPS, FTP 등을 통한 네트워크 요청을 처리하기 위한 오픈 소스, 이식성 및 기능이 풍부한 라이브러리입니다. 다음을 지원합니다:

  • GET, POST 및 기타 HTTP 요청 수행
  • 헤더 및 인증 처리
  • 응답을 효율적으로 처리합니다.

C에서 API를 사용하기 위한 기본 단계

JSON 데이터를 가져오는 실제 사례를 중심으로 C를 사용하여 API를 사용하는 과정을 살펴보겠습니다.

설정 및 설치

libcurl을 사용하려면 시스템에 libcurl을 설치해야 합니다. 대부분의 Linux 배포판에서는 다음을 사용하여 이 작업을 수행할 수 있습니다.

sudo apt-get install libcurl4-openssl-dev

Windows에서는 libcurl 웹사이트(https://curl.se/download.html)에서 미리 컴파일된 바이너리를 다운로드할 수 있습니다.

macOS에서 Homebrew를 사용하는 경우 다음을 통해 설치할 수 있습니다

brew install curl

C 프로그램 구조화

API에서 데이터를 가져오는 간단한 C 프로그램에는 다음 구성 요소가 포함됩니다.

  • libcurl을 초기화하는 중입니다.
  • API 요청 구성(URL, HTTP 메소드, 헤더 등)
  • 응답을 받고 저장합니다.
  • 자원을 정리합니다.

다음은 공개 API에서 JSON 데이터를 가져오는 예제 프로그램입니다.

sudo apt-get install libcurl4-openssl-dev

실행 단계

코드를 파일(예: get.c.)에 저장하세요.
다음 명령을 사용하여 컴파일하십시오.

brew install curl

컴파일된 프로그램 실행:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

// 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] = '<pre class="brush:php;toolbar:false">gcc get.c -o get -lcurl
'; 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; }

libcurl을 사용한 HTTP 응답의 콜백 메커니즘 이해

C에서 HTTP 응답을 처리하기 위해 libcurl을 사용할 때 콜백 함수의 동작을 이해하는 것이 중요합니다. ResponseCallback 함수와 같이 응답 데이터를 처리하기 위해 정의한 콜백 함수는 단일 HTTP 응답에 대해 여러 번 호출될 수 있습니다. 이것이 작동하는 이유와 방법은 다음과 같습니다.

콜백이 여러 번 호출되는 이유는 무엇입니까?

libcurl의 콜백 메커니즘은 데이터를 효율적이고 유연하게 처리하도록 설계되었습니다. 전체 응답을 처리하기 전에 다운로드되는 것을 기다리는 대신, libcurl은 응답을 더 작은 청크로 처리하여 각 청크가 수신될 때 콜백 함수를 호출합니다.

이 동작으로 인해 다음이 가능합니다.

  • 효율적인 메모리 사용: 청크를 증분식으로 처리하면 전체 응답에 대해 큰 메모리 블록을 미리 할당할 필요가 없습니다.
  • 스트리밍 처리: 각 청크가 도착하면 이를 처리하거나 조치를 취할 수 있습니다. 이는 대규모 응답을 스트리밍하거나 실시간으로 데이터를 처리하는 데 유용합니다.

어떻게 작동하나요?
서버로부터 데이터 덩어리가 수신될 때마다 libcurl은 콜백 함수를 호출합니다. 각 청크의 크기는 네트워크 상태, 버퍼 크기 및 libcurl의 내부 논리에 따라 다릅니다.
콜백은 청크를 축적하여 궁극적으로 전체 응답을 재구성해야 합니다.

다음은 예시 시퀀스입니다.

  1. 서버가 응답을 보내기 시작합니다.
  2. libcurl은 첫 번째 청크를 수신하고 콜백을 호출합니다.
  3. 콜백은 청크를 처리하거나 저장합니다.
  4. libcurl은 다음 청크를 수신하고 콜백을 다시 호출합니다.
  5. 이 과정은 전체 응답을 받을 때까지 계속됩니다.

ResponseCallback 함수에 대한 단계별 소스 코드 설명

ResponseCallback은 libcurl이 데이터를 수신할 때 호출되는 함수입니다.

함수 선언

sudo apt-get install libcurl4-openssl-dev
  • void *contents: 서버로부터 받은 데이터에 대한 포인터입니다. libcurl은 이 버퍼를 제공하고 다운로드한 데이터로 채웁니다.
  • size_t size 및 size_t nmemb: 각 메모리 블록의 크기(size)와 블록 수(nmemb)를 나타냅니다. size * nmemb를 합치면 이 청크에 수신된 데이터의 전체 크기를 알 수 있습니다.
  • void *userp: 이것은 curl_easy_setopt(curl, CURLOPT_WRITEDATA, ...)를 통해 콜백 함수에 전달되는 사용자 정의 포인터입니다. 이 예에서는 전체 응답을 저장하는 구조체 Memory 개체에 대한 포인터입니다.

총 데이터 크기 계산

brew install curl

한 블록의 크기(size)에 블록 수(nmemb)를 곱하여 현재 수신된 데이터 청크의 전체 크기를 계산합니다.
예를 들어 서버가 각각 256바이트의 블록 8개를 전송하는 경우 totalSize는 8 * 256 = 2048바이트가 됩니다.

사용자 데이터에 액세스(구조적 메모리)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>

// 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] = '<pre class="brush:php;toolbar:false">gcc get.c -o get -lcurl
'; 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; }

userp 포인터는 구조체 Memory *로 캐스팅됩니다. 이 구조체는 메인 프로그램 초기에 전달되었으며 수신된 데이터를 축적하는 데 사용됩니다.

구조체 Memory는 다음과 같이 정의됩니다.

./get
  • 응답: 다운로드된 데이터를 저장하는 동적으로 할당된 문자열입니다.
  • size: 응답 문자열의 현재 크기입니다.

메모리 재할당

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

새 데이터 청크를 수용하도록 응답 버퍼 크기를 조정합니다.

  • mem->size: 버퍼의 현재 크기.
  • totalSize: 새 청크의 크기입니다.
  • 1: null 종결자( )를 위한 공백으로 유효한 C 문자열을 만듭니다.
  • realloc: 응답 버퍼에 대한 메모리를 동적으로 재할당합니다.

할당이 실패하면 realloc은 NULL을 반환하고 이전 메모리는 유효한 상태로 유지됩니다.

메모리 할당 오류 처리

size_t totalSize = size * nmemb;

메모리 할당이 실패하면(즉 ptr은 NULL임) 오류 메시지를 인쇄하고 0을 반환합니다. 0을 반환하면 libcurl에 전송을 중단하라는 신호가 전달됩니다.

버퍼 업데이트

struct Memory *mem = (struct Memory *)userp;
  • mem->response = ptr: 새로 할당된 메모리를 다시 응답 포인터에 할당합니다.
  • memcpy: 콘텐츠의 새 데이터 덩어리를 버퍼에 복사합니다.
    • &(mem->response[mem->size]): 새 데이터가 추가되어야 하는 버퍼 내 위치(현재 데이터의 끝).
    • 내용: 서버로부터 받은 데이터입니다.
    • totalSize: 복사할 데이터의 크기입니다.

전체 크기 업데이트

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

새 청크를 추가한 후 새 전체 크기를 반영하도록 응답 버퍼의 크기를 늘립니다.

Null-응답 문자열 종료

sudo apt-get install libcurl4-openssl-dev

응답 버퍼 끝에 null 종결자를 추가하여 유효한 C 문자열로 만듭니다.
이렇게 하면 응답이 일반 null 종료 문자열로 안전하게 처리될 수 있습니다.

전체 크기를 반환합니다.

brew install curl

처리된 바이트 수(totalSize)를 반환합니다.
이는 데이터 청크가 성공적으로 처리되었음을 libcurl에 알립니다.

API로 C를 선택하는 경우

다음과 같은 경우 API를 사용하기 위해 C를 사용합니다.

  • 성능 문제: C는 속도가 중요한 애플리케이션에 이상적입니다.
  • 시스템 통합: 네트워크 요청과 하드웨어 작업(예: PoS 시스템에 대한 데이터 가져오기)을 결합해야 합니다.
  • 임베디드 시스템: 리소스가 제한된 장치는 C의 효율성을 활용합니다.
  • 호기심과 탐색: 때로는 단지 프로그래밍을 즐기고 종종 상위 레벨 언어에서만 사용되는 작업을 위해 하위 레벨 언어를 탐색하여 도전하고 싶기 때문에 C를 사용하는 경우도 있습니다. 이는 내부적으로 작동하는 방식에 대한 이해를 심화할 수 있는 좋은 방법입니다!

결론

C에서 API를 사용하는 것은 오늘날의 고급 프로그래밍 세계에서는 색다른 것처럼 보일 수 있지만 성능, 제어 및 시스템 수준 작업과의 통합이 필요한 시나리오를 위한 강력한 도구입니다. libcurl과 같은 라이브러리를 사용하면 개발자는 HTTP 요청을 C 애플리케이션에 쉽게 통합하여 최신 API와 기존 시스템 수준 프로그래밍 간의 격차를 해소할 수 있습니다.

이러한 지식을 바탕으로 API와 원활하게 상호 작용하는 C 애플리케이션을 구축하여 최신 개발 워크플로에서도 C가 여전히 관련성을 유지한다는 것을 입증할 수 있습니다.

위 내용은 C에서 API 사용: 현대 개발자를 위한 실용적인 가이드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.