c - 在 C 中的服务器和客户端应用程序中通过套接字发送和接收 JSON

标签 c json sockets

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.

通过学习一些教程,我能够创建 JSON 对象并成功解析它。

现在我想使用JSON数据格式来进行服务端与客户端的通信。

这是我的服务器和客户端代码的一部分

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;
}

客户端.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;
}

我想将 json_object jobj 从客户端发送到服务器。 如何做到这一点?

我尝试过的一些事情:

  1. 当我使用write(fd, jobj, sizeof(jobj))时,当我在服务器上接收数据时,客户端只发送8个字节,其他字符为空。

  2. 当我使用 write(fd, json_object_to_json_string(jobj), 157) 时,我只能发送完整的 json_object jobj,其中 157 是该 jobj 对象中的字符总数。

  3. 如果我在服务器端使用 read(connfd, jobj, sizeof(jobj)) 那么我只能接收 8 个字节(在客户端我使用 write( fd, jobj, sizeof(jobj))).

  4. 如果我使用上面的 server.c,我能够接收完整的 JSON 对象(如果我已经知道该对象中的字符数)。但它是原始格式(逐字节接收)。

如何从客户端发送完整的json_object jobj?

服务器端如何接收完整的json_object jobj?

最佳答案

1) jobj 是一个指针,所以当你使用

write(fd, jobj, sizeof(jobj))

你正在写一个指向那个对象的指针,而不是那个对象。

3) 同前。

也许你应该尝试用类似的东西发送它

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

在接收端,你应该做一个for循环,比如

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

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

如果你知道 json 的最大 SIZE,否则结合使用 malloc()realloc()

编辑:

我这样做了,现在它工作正常。

客户端.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 是一个宏,指定最大缓冲区长度,您可以随意设置。 下次请粘贴您的所有代码(包括 #include ...)并正确缩进。

关于c - 在 C 中的服务器和客户端应用程序中通过套接字发送和接收 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32667109/

相关文章:

java - 如何通过 ListView 传递数据,Android - Java

android - Gson 预期为 BEGIN_ARRAY 但在第 1 行第 2 列路径为 BEGIN_OBJECT $

java - 如何使用NIO套接字只写入一次或 "on some command"?

c - sem_wait 上的线程阻塞导致其他线程挂起

c - 如何从C中的dll获取模拟器(.exe)路径

C fgets 会跳过用户输入,即使在刷新缓冲区时也是如此

java - 使用 JAVA 的 JSONObject 中的参数数组

node.js - 如何在socket.io中获取客户端IP地址

python : How to connect socket on different network

c++ - 将所有重音字母更改为 C++ 中的普通字母