2016-11-17 3 views
0

Я пытаюсь написать клиента REST в C. В настоящее время он является автономным, но позже я планирую его перенести на нашу кодовую базу.Клиент REST в C

Я тестирую это на centos 6.5 с gcc.

Я начал с кода в https://gist.github.com/nolim1t/126991 в качестве ссылки. Это было предложено в quora несколькими членами.

Я изменил приведенный выше код в соответствии с моими потребностями. Когда я попробовал это, я не могу получить действительный ответ от остального сервера.

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <netinet/tcp.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <netdb.h> 

int socket_connect(char *host, in_port_t port){ 
    struct hostent *hp; 
    struct sockaddr_in addr; 
    int on = 1, sock; 
    if((hp = gethostbyname(host)) == NULL){ 
    herror("gethostbyname"); 
    exit(1); 
} 
    bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); 
    addr.sin_port = htons(port); 
    addr.sin_family = AF_INET; 
    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&on, sizeof(int)); 

    if(sock == -1){ 
     perror("setsockopt"); 
     exit(1); 
    } 

    if(connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1){ 
     perror("connect"); 
     exit(1); 
    } 
    return sock; 
} 

#define BUFFER_SIZE 1024 

int main(int argc, char *argv[]){ 
    int fd; 
    int cx; 
    char inputBuffer[BUFFER_SIZE]; 
    char buffer[BUFFER_SIZE]; 
    if(argc < 4){ 
     fprintf(stderr, "Usage: %s <hostname> <port> <other-args>\n", argv[0]); 
     exit(1); 
    } 
    fd = socket_connect(argv[1], atoi(argv[2])); 
    if(fd) 
    { 
     printf("socket success\n"); 
    } 

    cx = snprintf(inputBuffer, BUFFER_SIZE, "GET %s\r\n", argv[3]); 
// snprintf(inputBuffer, argv[3], strlen(argv[3])); 

    write(fd, inputBuffer, cx); // write(fd, char[]*, len); 
    bzero(buffer, BUFFER_SIZE); 
    printf("reading response\n"); 
    while(read(fd, buffer, BUFFER_SIZE - 1) != 0){ 
     fprintf(stderr, "%s", buffer); 
     bzero(buffer, BUFFER_SIZE); 
    } 
    shutdown(fd, SHUT_RDWR); 
    close(fd); 
    return 0; 
} 

Это остальное как URL, что я доступ: http://maps.googleapis.com/maps/api/geocode/json?address=chicago

Когда я иду к нему через браузер я могу получить доступ к данным JSON/ответ. Однако, когда я использую программу C, я получаю следующий вывод.

#./rest maps.googleapis.com 80 /maps/api/geocode/json?address=chicago 
socket success 
reading response 

И он остается там на неопределенный срок.

У меня есть пакеты захвата и поток tcp, когда я получаю доступ через программу C, а также через браузер.

Packet Capture when I use the C program

TCP stream for the C program request

packet capture for browser request

Edit:

Спасибо за ответы. Моя оригинальная программа сработала. Отладил это и обнаружил, что корпоративный брандмауэр блокировал пакеты, и поэтому я так и не получил ответа.

Для ответа, отправленного @eyllanesc - Этот код работает частично. По какой-то неизвестной причине пакет FIN с сервера не приходит сразу. Он всегда занимает 4 минуты с момента отправки первого пакета данных. Так что программа держится на 4 минуты, прежде чем она закончится. Спасибо за усилия, хотя.

+1

Не повторяется, './ your_prog maps.googleapis .com 80 "/ maps/api/geocode/json? address = chicago" 'выплюнуть правильный результат – deamentiaemundi

+0

Спасибо. Да, это была проблема с окружающей средой. –

ответ

1

Мое решение основано на следующем link

Мое решение:

#include <stdio.h> /* printf, sprintf */ 
#include <string.h> 
#include <stdlib.h> /* exit */ 
#include <unistd.h> /* read, write, close */ 
#include <string.h> /* memcpy, memset */ 
#include <sys/socket.h> /* socket, connect */ 
#include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */ 
#include <netdb.h> /* struct hostent, gethostbyname */ 

void error(const char *msg) { perror(msg); exit(0); } 

int main(int argc,char *argv[]) 
{ 
    /* first what are we going to send and where are we going to send it? */ 

    if(argc < 4){ 
     fprintf(stderr, "Usage: %s <hostname> <port> <resource>\n", argv[0]); 
     exit(1); 
    } 

    char *host =   argv[1]; 
    int portno = atoi(argv[2]); 

    char message_fmt[1024]; 

    strcpy (message_fmt,"GET "); 
    strcat(message_fmt, argv[3]); 
    strcat(message_fmt," HTTP/1.0\r\n\r\n"); 

    struct hostent *server; 
    struct sockaddr_in serv_addr; 
    int sockfd, bytes, sent, received, total; 
    char message[1024],response[4096]; 

    /* fill in the parameters */ 
    sprintf(message,message_fmt,argv[1],argv[2]); 
    printf("Request:\n%s\n",message); 

    /* create the socket */ 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) error("ERROR opening socket"); 

    /* lookup the ip address */ 
    server = gethostbyname(host); 
    if (server == NULL) error("ERROR, no such host"); 

    /* fill in the structure */ 
    memset(&serv_addr,0,sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_port = htons(portno); 
    memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length); 

    /* connect the socket */ 
    if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) 
     error("ERROR connecting"); 

    /* send the request */ 
    total = strlen(message); 
    sent = 0; 
    do { 
     bytes = write(sockfd,message+sent,total-sent); 
     if (bytes < 0) 
      error("ERROR writing message to socket"); 
     if (bytes == 0) 
      break; 
     sent+=bytes; 
    } while (sent < total); 

    /* receive the response */ 
    memset(response,0,sizeof(response)); 
    total = sizeof(response)-1; 
    received = 0; 
    do { 
     bytes = read(sockfd,response+received,total-received); 
     if (bytes < 0) 
      error("ERROR reading response from socket"); 
     if (bytes == 0) 
      break; 
     received+=bytes; 
    } while (received < total); 

    if (received == total) 
     error("ERROR storing complete response from socket"); 

    /* close the socket */ 
    close(sockfd); 

    /* process response */ 
    printf("Response:\n%s\n",response); 

    return 0; 
} 

Вход:

./rest maps.googleapis.com 80 /maps/api/geocode/json?address=chicago 

Выход:

Request: 
GET /maps/api/geocode/json?address=chicago HTTP/1.0 


Response: 
HTTP/1.0 200 OK 
Content-Type: application/json; charset=UTF-8 
Date: Thu, 17 Nov 2016 04:01:52 GMT 
Expires: Fri, 18 Nov 2016 04:01:52 GMT 
Cache-Control: public, max-age=86400 
Access-Control-Allow-Origin: * 
Server: mafe 
X-XSS-Protection: 1; mode=block 
X-Frame-Options: SAMEORIGIN 
Accept-Ranges: none 
Vary: Accept-Language,Accept-Encoding 

{ 
    "results" : [ 
     { 
     "address_components" : [ 
      { 
       "long_name" : "Chicago", 
       "short_name" : "Chicago", 
       "types" : [ "locality", "political" ] 
      }, 
      { 
       "long_name" : "Cook County", 
       "short_name" : "Cook County", 
       "types" : [ "administrative_area_level_2", "political" ] 
      }, 
      { 
       "long_name" : "Illinois", 
       "short_name" : "IL", 
       "types" : [ "administrative_area_level_1", "political" ] 
      }, 
      { 
       "long_name" : "United States", 
       "short_name" : "US", 
       "types" : [ "country", "political" ] 
      } 
     ], 
     "formatted_address" : "Chicago, IL, USA", 
     "geometry" : { 
      "bounds" : { 
       "northeast" : { 
        "lat" : 42.023131, 
        "lng" : -87.52366099999999 
       }, 
       "southwest" : { 
        "lat" : 41.6443349, 
        "lng" : -87.9402669 
       } 
      }, 
      "location" : { 
       "lat" : 41.8781136, 
       "lng" : -87.6297982 
      }, 
      "location_type" : "APPROXIMATE", 
      "viewport" : { 
       "northeast" : { 
        "lat" : 42.023131, 
        "lng" : -87.52404399999999 
       }, 
       "southwest" : { 
        "lat" : 41.6443349, 
        "lng" : -87.9402669 
       } 
      } 
     }, 
     "place_id" : "ChIJ7cv00DwsDogRAMDACa2m4K8", 
     "types" : [ "locality", "political" ] 
     } 
    ], 
    "status" : "OK" 
} 
+0

Спасибо за внимание. Это все еще не работает полностью. См. Раздел редактирования вопроса. –

Смежные вопросы