Troublesome socket response on Android NDK

Asked

Viewed 128 times

1

I’m trying to implement this library, Parson, in C, but when I try to manipulate the data obtained via connection socket(ONLY link), I get a null, what doesn’t happen when I manually put the json in the C.

The problem is in the socket response, which is not received correctly, because in the android logcat everything before the answer is deleted, getting a blank field.

Below is the entire function used to get a response from the server.

#include "HttpGet.h"
#include <android/log.h>
#include <stdio.h> /* printf, sprintf */
#include <stdlib.h> /* exit, atoi, malloc, free */
#include <unistd.h> /* read, write, close */
#include <string.h> /* memcpy, memset */
#include <sys/socket.h> /* socket, connect */
#include <netdb.h> /* struct hostent, gethostbyname */
#include <netinet/in.h> /* struct sockaddr_in, struct sockaddr */
#include "parson.h" // JSON

int HttpGetPost(char *webserver,const char *url)
{
    __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Enter HttpGet function!");
          char* argva = "?tokenweb=meuapp";

      __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Enter argvs %s ",argva);



    int argc = 5;
      char* argv[7];
      argv[1] = "127.0.0.1";
      argv[2] = "80";
      argv[3] = "GET"; //POST //GET
      argv[4] = "/testmobile.php";
      argv[5] = "?tokenweb=meuapp";
      argv[6] = "";
      __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Enter argv2 %s ",argv[4]);

    int i;
    struct hostent *server;
    struct sockaddr_in serv_addr;
    int bytes, sent, received, total, message_size;
    char *message, response[4096];
    int portno = atoi(argv[2])>0?atoi(argv[2]):80;
    char *host = strlen(argv[1])>0?argv[1]:"localhost";
    char *path = strlen(argv[4])>0?argv[4]:"/";
    if (argc < 5) { puts("Parameters: <host> <port> <method> <path> [<data> [<headers>]]"); exit(0); }
    /* How big is the message? */
    message_size=0;
    if(!strcmp(argv[3],"GET"))
    {
                printf("Process 1\n");
        message_size+=strlen("%s %s%s%s HTTP/1.0\r\nHost: %s\r\n");        /* method         */
        message_size+=strlen(argv[3]);                         /* path           */
        message_size+=strlen(path);                         /* headers        */
        if(argc>5)
            message_size+=strlen(argv[5]);                     /* query string   */
        for(i=6;i<argc;i++)                                    /* headers        */
            message_size+=strlen(argv[i])+strlen("\r\n");
        message_size+=strlen("\r\n");                          /* blank line     */
    }
    else
    {
                printf("Process 2\n");
        message_size+=strlen("%s %s HTTP/1.0\r\nHost: %s\r\n");
        message_size+=strlen(argv[3]);                         /* method         */
        message_size+=strlen(path);                            /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            message_size+=strlen(argv[i])+strlen("\r\n");
        if(argc>5)
            message_size+=strlen("Content-Length: %d\r\n")+10; /* content length */
        message_size+=strlen("\r\n");                          /* blank line     */
        if(argc>5)
            message_size+=strlen(argv[5]);                     /* body           */
    }
            printf("Allocating...\n");
    /* allocate space for the message */
    //message=malloc(message_size); //original
    message=malloc(1024);

    /* fill in the parameters */
    if(!strcmp(argv[3],"GET"))
    {
        if(argc>5)
            sprintf(message,"%s %s%s%s HTTP/1.0\r\nHost: %s\r\n",
                strlen(argv[3])>0?argv[3]:"GET",               /* method         */
                path,                                          /* path           */
                strlen(argv[5])>0?"?":"",                      /* ?              */
                strlen(argv[5])>0?argv[5]:"",host);            /* query string   */
        else
            sprintf(message,"%s %s HTTP/1.0\r\nHost: %s\r\n",
                strlen(argv[3])>0?argv[3]:"GET",               /* method         */
                path,host);                                    /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            {strcat(message,argv[i]);strcat(message,"\r\n");}
        strcat(message,"\r\n");                                /* blank line     */
    }
    else
    {
        sprintf(message,"%s %s HTTP/1.0\r\nHost: %s\r\n",
            strlen(argv[3])>0?argv[3]:"POST",                  /* method         */
            path,host);                                        /* path           */
        for(i=6;i<argc;i++)                                    /* headers        */
            {strcat(message,argv[i]);strcat(message,"\r\n");}
        if(argc>5)
            sprintf(message+strlen(message),"Content-Length: %d\r\n",(int)strlen(argv[5]));
        strcat(message,"\r\n");                                /* blank line     */
        if(argc>5)
            strcat(message,argv[5]);                           /* body           */
    }
    printf("Processed\n");
    /* What are we going to send? */
    printf("Request:\n%s\n",message);
        /* lookup the ip address */

    total = strlen(message);
    /* create the socket */


    int sockfd;
    server = gethostbyname(host);
    if (server == NULL) {
        error("ERROR, no such host");
        __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "ERROR, no such host");
    }
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) {
            error("ERROR opening socket");
            __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "ERROR opening socket");
        }
        /* 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");
            __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "ERROR connecting");
        }
                /* send the request */

    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;
    printf("Response: \n");

    /*
    do {
       printf("%s", response);
       __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Response: \n %s", response);

       //strcat(json_response, response);
       //strcpy(json_response,  response);
       json_response = response;

       memset(response, 0, sizeof(response));
       bytes = recv(sockfd, response, 1024, 0);
        if (bytes < 0)
           printf("ERROR reading response from socket");
       if (bytes == 0)
           break;
       received+=bytes;
    } while (1);
    */
    do {
        bytes = read(sockfd,response+received,total-received);
        __android_log_print(ANDROID_LOG_INFO, "---from--jni-RN---", "Response: %s", response);
        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");

    //__android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Response2: \n %s", response);


//============ Verificação de Segurança =================================================//
      __android_log_print(ANDROID_LOG_INFO, "-----from--jni-1-----", "Response: \"%s\"", response); // = {"message":"success"}"
      __android_log_print(ANDROID_LOG_INFO, "-----from--jni-1a-----", "Response: '%s'", response);

      JSON_Value *user_data = json_parse_string(response);

      const char *msgs = json_object_get_string(json_object(user_data), "message");

    //Auth HashCode
//  __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Response Compare: \n [%s]", name );
        __android_log_print(ANDROID_LOG_INFO, "-----from--jni-1-----", "Json Message  1. [%s] ", msgs);
        //__android_log_print(ANDROID_LOG_INFO, "-----from--jni-2-----", "Signature Auth 2. [%s] \n",signature);

    //Auth PackageName

    char text[100] = "{\"key\": \"valor\"}";
    JSON_Value *data = json_parse_string(text);
    const char *sdata = json_object_get_string(json_object(data), "key");
    __android_log_print(ANDROID_LOG_INFO, "-----from--jni-1-----", "Json Key  1. [%s] \n", sdata);

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

    free(message);
    return 0;
}

Running the above code I get the following message in logcat.

com.dou361.ijkplayer_simple.example I/-----from--jni-------: Enter mmain function!
com.dou361.ijkplayer_simple.example I/-----from--jni-------: Enter HttpGet function!
com.dou361.ijkplayer_simple.example I/-----from--jni-------: Enter argvs ?tokenweb=meuapp 
com.dou361.ijkplayer_simple.example I/-----from--jni-------: Enter argv2 /testmobile.php 
                                                             testando_msg
                                                             testando_msg
                                                             testando_msg"
                                                             testando_msg'
com.dou361.ijkplayer_simple.example I/-----from--jni-1-----: Json Message  1. [(null)] 
com.dou361.ijkplayer_simple.example I/-----from--jni-1-----: Json Key  1. [valor] 

Imagery inserir a descrição da imagem aqui

How could I receive that answer correctly? For example com.dou361.ijkplayer_simple.example I/-----from--jni-1-----: Json Message [testando_msg].

  • Sorry for the mess, they were many attempts, the answer comes, but it comes like this, with problems, and ends up serving for nothing.

  • The question has already been solved, any answers that are better than mine, or contain detailed explanations of each function and/or other ways to achieve what is desired here are welcome and can take the 50 dots.

1 answer

0


The solution found, however not the most desired is below, using the do/while in a loop which occurs 2 times, it is possible to bypass the null which is received when trying to obtain the response. Like the response is being processed in loop, is received 2 values, the first the null, and the second the desired variable. Through the if(msgs) it is possible to ignore the null and receive the desired data.

Follow the modified section.

do {
  char * httpbody = strstr(response, "{\"message\"");

  JSON_Value * user_data = json_parse_string(httpbody);
  const char * msgs = json_object_get_string(json_object(user_data), "message");

  if (msgs) {
    __android_log_print(ANDROID_LOG_INFO, "---from--jni----", "Response:[%s]", httpbody);
    __android_log_print(ANDROID_LOG_INFO, "---from--jni-json-", "Json Message [%s]", msgs);
  }
  bytes = recv(sockfd, response, 1024, 0);
  if (bytes < 0)
    printf("ERROR reading response from socket");
  if (bytes == 0)
    break;
  received += bytes;
} while (1);

With this, it is possible to ignore the \r\n or Blank line which is received with the response.

Desired result obtained:

com.dou361.ijkplayer_simple.example I/---from--jni----: Response:[{"message":"success"}]
com.dou361.ijkplayer_simple.example I/---from--jni-json-: Json Message [success]

Browser other questions tagged

You are not signed in. Login or sign up in order to post.