Edge Goldberg Edge Goldberg - 1 month ago 6
JSON Question

send and receive JSON over sockets in server and client application in C


I want to send the data in JSON over sockets in a server-client
application written in C.

I am using json-c / libjson library for handling JSON data in C
application.


By working on some of the tutorials I am able to create JSON object and able to parse it successfully.

Now I want to use the JSON data format for the communication of server-client.

Here is part of my server and client code

server.c

int main()
{
int listenfd = 0, connfd = 0; //related with the server
struct sockaddr_in serv_addr;

//json_object * jobj;
uint8_t buf[158], i;

memset(&buf, '0', sizeof(buf));
listenfd = socket(AF_INET, SOCK_STREAM, 0);

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(8888);

bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
printf("binding\n");

listen(listenfd, 5);
printf("listening\n");
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);

printf("Reading from client\n");

while ( (read(connfd, buf, 157)) > 0 )
{
for ( i = 0; i < 157; i++ )
//printf("%s\n", json_object_to_json_string(jobj));
//json_parse(jobj);
printf("%d\n", buf[i]);
}

return 0;
}


client.c

int main()
{
char* str;
int fd = 0;
struct sockaddr_in demoserverAddr;

fd = socket(AF_INET, SOCK_STREAM, 0);

if (fd < 0)
{
printf("Error : Could not create socket\n");
return 1;
}
else
{
demoserverAddr.sin_family = AF_INET;
demoserverAddr.sin_port = htons(8888);
demoserverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(demoserverAddr.sin_zero, '\0', sizeof(demoserverAddr.sin_zero));
}

if (connect(fd, (const struct sockaddr *)&demoserverAddr, sizeof(demoserverAddr)) < 0)
{
printf("ERROR connecting to server\n");
return 1;
}

/*Creating a json object*/
json_object *jobj = json_object_new_object();

/*Creating a json string*/
json_object *jstring = json_object_new_string("Joys of Programming");

/*Creating a json integer*/
json_object *jint = json_object_new_int(10);

/*Creating a json boolean*/
json_object *jboolean = json_object_new_boolean(1);

/*Creating a json double*/
json_object *jdouble = json_object_new_double(2.14);

/*Creating a json array*/
json_object *jarray = json_object_new_array();

/*Creating json strings*/
json_object *jstring1 = json_object_new_string("c");
json_object *jstring2 = json_object_new_string("c++");
json_object *jstring3 = json_object_new_string("php");

/*Adding the above created json strings to the array*/
json_object_array_add(jarray,jstring1);
json_object_array_add(jarray,jstring2);
json_object_array_add(jarray,jstring3);

/*Form the json object*/
/*Each of these is like a key value pair*/
json_object_object_add(jobj,"Site Name", jstring);
json_object_object_add(jobj,"Technical blog", jboolean);
json_object_object_add(jobj,"Average posts per day", jdouble);
json_object_object_add(jobj,"Number of posts", jint);
json_object_object_add(jobj,"Categories", jarray);

printf("Size of JSON object- %lu\n", sizeof(jobj));
printf("Size of JSON_TO_STRING- %lu,\n %s\n", sizeof(json_object_to_json_string(jobj)), json_object_to_json_string(jobj));

//printf("Size of string- %lu\n", sizeof(json_object_to_json_string(jobj)));
write(fd, json_object_to_json_string(jobj), 157);

printf("Written data\n");
return 0;
}


I want to send the json_object jobj from client to server.
How to do this?

Some things that I tried:


  1. When I use write(fd, jobj, sizeof(jobj)) , the client sends only 8 bytes and other characters are null when I receive data on server.

  2. I am only able to send complete json_object jobj when I use write(fd, json_object_to_json_string(jobj), 157) where 157 is the total number of characters in that jobj object.

  3. On server side if I use read(connfd, jobj, sizeof(jobj)) then I only able to receive 8 bytes (on client side I am using write(fd, jobj, sizeof(jobj))).

  4. If I use the above server.c I am able to receive complete JSON object (if I already know the number of characters in that object). But it is in raw format (receiving byte by byte).



How to send the complete json_object jobj from client side?

And how to receive the complete json_object jobj on server side?

Answer

1) jobj is a pointer, so when you use

write(fd, jobj, sizeof(jobj))

you're writing a pointer to that object, not that object.

3) Same as before.

Maybe you should try sending it with something like

if (write(fd, jobj, sizeof(*jobj)) == -1)
    /* error handler /*

On the receive side, you should do a for loop, like

for (;;)
{
    r = read(fd, jobj, SIZE);

    if (r == -1)
        /*error handler*/
    if (r == 0)
        break;
}

if you know the maximum SIZE of the json, or combine malloc() and realloc() otherwise

EDIT:

I did this, and now it works fine.

client.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <json/json.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main()
{
    /* all previous code until
    printf("Size of string- %lu\n", sizeof(json_object_to_json_string(jobj)))*/

    char temp_buff[MAX_SIZE];

    if (strcpy(temp_buff, json_object_to_json_string(jobj)) == NULL)
    {
        perror("strcpy");
        return EXIT_FAILURE;
    }

    if (write(fd, temp_buff, strlen(temp_buff)) == -1)
    {
        perror("write");
        return EXIT_FAILURE;
    }

    printf("Written data\n");
    return EXIT_SUCCESS;
}

server.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <json/json.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main()
{
    /* all previous code until
    printf("Reading from client\n"); */

    ssize_t r;

    char buff[MAX_SIZE];

    for (;;)
    {
        r = read(connfd, buff, MAX_SIZE);

        if (r == -1)
        {
            perror("read");
            return EXIT_FAILURE;
        }
        if (r == 0)
            break;

        printf("READ: %s\n", buff);
    }

    return EXIT_SUCCESS;
}

MAX_SIZE is a macro that specifies the maximum buffer length, set it as you wish. Please next time paste ALL your code (including the #include ...) and indent it properly.

Comments