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

前端 未结 2 1548
长发绾君心
长发绾君心 2021-02-03 14:42

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

相关标签:
2条回答
  • 2021-02-03 15:13

    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.

    0 讨论(0)
  • 2021-02-03 15:22

    To use TCP socket messages you have the client and server learn how to interpret the messages.

    HTTP, for example, uses the 2 characters \r\n as end of message Another alternative option is to send the size of the message before the message.

    Here's a solution that does that using the JSON Jansson library. It adds the size as a sequence of characters (e.g "123", is later parsed as integer 123), adding the character "#" as end of size header then the JSON text representation of the JSON object (as defined by the Jansson library)

    size_t socket_t::write(json_t *json)
    {
      char *buf_json = NULL;
      std::string buf_send;
      size_t size_json;
    
      //get char* from json_t
      buf_json = json_dumps(json, JSON_PRESERVE_ORDER);
      size_json = strlen(buf_json);
      //construct send buffer, adding a header with size in bytes of JSON and # terminator
      buf_send = std::to_string(static_cast<long long unsigned int>(size_json));
      buf_send += "#";
      buf_send += std::string(buf_json);
    
      this->write(buf_send.data(), buf_send.size());
    
      free(buf_json);
      return buf_send.size();
    }
    

    The reading is done with

    json_t * socket_t::read()
    {
      int recv_size; // size in bytes received or -1 on error 
      const int size_buf = 20;
      char buf[size_buf];
    
      //peek header
      if ((recv_size = recv(m_socket, buf, size_buf, MSG_PEEK)) == -1)
      {
        std::cout << "recv error: " << strerror(errno) << std::endl;
      }
    
      //get size of JSON message
      std::string str(buf);
      size_t pos = str.find("#");
      std::string str_header(str.substr(0, pos));
    
      //parse header
      if ((recv_size = recv(m_socket, buf, str_header.size() + 1, 0)) == -1)
      {
        std::cout << "recv error: " << strerror(errno) << std::endl;
      }
    
      //sanity check
      buf[recv_size - 1] = '\0';
      assert(str_header.compare(buf) == 0);
    
      size_t size_json = static_cast<size_t>(std::stoull(str_header));
      std::string str_buf = read_all(size_json);
      //terminate buffer with size
      std::string str_json = str_buf.substr(0, size_json);
    
      //construct JSON
      json_error_t *err = NULL;
      json_t *json = json_loadb(str_json.data(), str_json.size(), JSON_PRESERVE_ORDER, err);
      return json;
    }
    

    This is implemented in

    https://github.com/pedro-vicente/lib_netsockets

    0 讨论(0)
提交回复
热议问题