2012-05-23 48 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) ,因为服务器可能将头部和内容作为单独的块发送。