send and receive JSON over sockets in server and client application in C
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.
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 messageAnother 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