2012-05-23 49 views
-1

我正在嘗試編寫一個簡單的客戶端C,它將與Google搜索API進行交互並返回搜索結果。我能夠發送一個搜索請求,並以200 OK代碼和一些標題文本獲得響應,但是沒有搜索結果。難道我做錯了什麼?Google定製搜索結果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 openssl/rand.h 
#include openssl/ssl.h 
#include openssl/err.h 

// Simple structure to keep track of the handle, and 
// of what needs to be freed later. 
typedef struct { 
    int socket; 
    SSL *sslHandle; 
    SSL_CTX *sslContext; 
} connection; 

// For this example, we'll be testing on openssl.org 
#define KEY  "/customsearch/v1?key=AIzaSyAOdB5MgAEmvzglw05rR1OPYEYgFuZrT9o&cx=003397780648636422832:u25rx3s92ro&q=" 
#define SERVER "www.googleapis.com" 
#define PORT 443 

// Establish a regular tcp connection 
int tcpConnect() 
{ 
    int error, handle; 
    struct hostent *host; 
    struct sockaddr_in server; 

    host = gethostbyname (SERVER); 
    handle = socket (AF_INET, SOCK_STREAM, 0); 
    if (handle == -1) 
    { 
     perror ("Socket"); 
     handle = 0; 
    } 
    else 
    { 
     server.sin_family = AF_INET; 
     server.sin_port = htons (PORT); 
     server.sin_addr = *((struct in_addr *) host->h_addr); 
     bzero (&(server.sin_zero), 8); 

     error = connect (handle, (struct sockaddr *) &server, 
         sizeof (struct sockaddr)); 
     if (error == -1) 
     { 
      perror ("Connect"); 
      handle = 0; 
     } 
    } 

    return handle; 
} 

// Establish a connection using an SSL layer 
connection *sslConnect (void) 
{ 
    connection *c; 

    c = malloc (sizeof (connection)); 
    c->sslHandle = NULL; 
    c->sslContext = NULL; 

    c->socket = tcpConnect(); 
    if (c->socket) 
    { 
     // Register the error strings for libcrypto & libssl 
     SSL_load_error_strings(); 
     // Register the available ciphers and digests 
     SSL_library_init(); 

     // New context saying we are a client, and using SSL 2 or 3 
     c->sslContext = SSL_CTX_new (SSLv23_client_method()); 
     if (c->sslContext == NULL) 
     ERR_print_errors_fp (stderr); 

     // Create an SSL struct for the connection 
     c->sslHandle = SSL_new (c->sslContext); 
     if (c->sslHandle == NULL) 
     ERR_print_errors_fp (stderr); 

     // Connect the SSL struct to our connection 
     if (!SSL_set_fd (c->sslHandle, c->socket)) 
     ERR_print_errors_fp (stderr); 

     // Initiate SSL handshake 
     if (SSL_connect (c->sslHandle) != 1) 
     ERR_print_errors_fp (stderr); 
    } 
    else 
    { 
     perror ("Connect failed"); 
    } 

    return c; 
} 

// Disconnect & free connection struct 
void sslDisconnect (connection *c) 
{ 
    if (c->socket) 
    close (c->socket); 
    if (c->sslHandle) 
    { 
     SSL_shutdown (c->sslHandle); 
     SSL_free (c->sslHandle); 
    } 
    if (c->sslContext) 
    SSL_CTX_free (c->sslContext); 

    free (c); 
} 

// Read all available text from the connection 
char *sslRead (connection *c) 
{ 
    const int readSize = 2048; 
    char *rc = NULL; 
    int received, count = 0; 
    char buffer[2048]; 

    if (c) 
    { 
     while (1) 
     { 
      if (!rc) 
      rc = malloc (readSize * sizeof (char) + 1); 
      else 
      rc = realloc (rc, (count + 1) * 
          readSize * sizeof (char) + 1); 

      received = SSL_read (c->sslHandle, buffer, readSize); 
      buffer[received] = '\0'; 

      if (received > 0) 
      strcat (rc, buffer); 

      if (received < readSize) 
      break; 
      count++; 
     } 
    } 

    return rc; 
} 

// Write text to the connection 
void sslWrite (connection *c, char *text) 
{ 
    if (c) 
    SSL_write (c->sslHandle, text, strlen (text) 
} 

// Very basic main: we send GET/and print the response. 
int main (int argc, char **argv) 
{ 
    connection *c; 
    char *response; 
    char request[512]=""; 

    c = sslConnect(); 

    sprintf(request, "GET https://%s%s%s\r\n\r\n", SERVER, KEY, argv[1]); 
    printf("%s", request); 

    sslWrite (c, request); 

    response = sslRead (c); 

    printf ("%s\n", response); 

    sslDisconnect (c); 
    free (response); 

    return 0; 
} 

這裏是我的結果(運行 「APP_NAME火爐」):

^h AEA * HTTP/1.0 200 OK

到期日:星期三,23 May 2012 05:49:58 GMT

Date:Wed,23 May 2012 05:49:58 GMT

緩存控制:私人,最大年齡= 0,必須-重新驗證,無轉換

ETag的: 「ewDGMApuuzSJ2mUepyXm8PLTiIU/uPd2cbC0DjaL0y0Y6HiAvzSqSts」

內容類型:應用/ JSON;字符集= UTF-8

X-的Content-Type-選項:nosniff

X框-選項:SAMEORIGIN

X-XSS-保護:1;模式=塊

服務器:GSE


必須有比沒有在那裏大約竈肯定的詳細信息,對不對?

+0

爲什麼要編寫自己的HTTP接口,而不是使用[cURL](http://curl.haxx.se/libcurl/)之類的東西? –

+1

看起來你已經在緩衝區之前獲得了一些垃圾。沒有看到你的代碼,這裏沒有人甚至可以猜測你的問題是什麼。 – Mat

+0

@JoachimPileborg - 我計劃使用libcurl後,我得到這個原型的工作。我正在學習與Web客戶端進行交互,並希望儘可能從最低層開始。 – Vistian

回答

0

在上述代碼中的兩個問題是#1)的rc開始不被初始化爲零malloc後和使用前strcat - 這導致垃圾字符,和#2)的線if (received < readSize)if (received == 0) ,因爲服務器可能將頭部和內容作爲單獨的塊發送。