四、与服务器进行数据交换

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

一、json-c

json是一种轻量级的数据交换格式json选用完全独立于语言的文本格局。

jdon格式

json数据的书写格式是键/值对

json键值对用来保存js对象的一种方式键/值对包括字段名称在双引号中后面写一个冒号然后是值。

JSON 值可以是字符串在双引号中、数组在中括号中、数字整数或浮点数、逻辑值true 或 false、对象在大括号中、 null。

Json结构

json结构有两种就是对象和数组通过这两种结构可以表示各种复杂的结构

{"province": "Shanxi"} 可以理解为是一个包含province为Shanxi的对象

["Shanxi","Shandong"]这是一个包含两个元素的数组

[{"province": "Shanxi"},{"province": "Shandong"}] 就表示包含两个对象的数组。

当然了,你也可以使用 {"province":["Shanxi","Shandong"]} 来简化上面的JSON,这是一个拥有一个name数组的对象。

下面是一小段JSON代码

{“skillz”: {“web”:[ {“name”: “html” “years”: “5” } {“name”: “css” “years”: “3” }],”database”:[ {“name”: “sql” “years”: “7” }]}}

花括弧方括弧冒号和逗号

花括弧表示一个“容器”

方括号装载数组

名称和值用冒号隔开

数组元素通过逗号隔开

json-c数据类型

typedef enum json_type {
  /* If you change this, be sure to update json_type_to_name() too */
  json_type_null,
  json_type_boolean,
  json_type_double,
  json_type_int,
  json_type_object,
  json_type_array,
  json_type_string,
} json_type;

基础API

struct json_object * json_object_new_object();

//创建个空的json_type_object类型的JSON对象

struct json_object* json_object_new_boolean(Boolean b);

//创建个json_type_boolean值类型json对象

int json_object_get_int(struct json_object *obj);

//从json对象中int值类型得到int值

struct json_object * json_object_new_array();

//创建个空的json_type_array类型JSON数组值对象

struct json_object * json_tokener_parse(char *str);

//由str里的JSON字符串生成JSON对象str是json_object_to_json_string() 生成的。
参数

str :json字符串

struct json_object * json_object_object_get(struct json_object * json,char *name);

//从json中按名字取一个对象。

参数

json :json对象

name : json域名字

Int json_object_is_type(struct json_object * this, enum json_type type)

//检查json_object是json的某个类型

参数

this: json_object 实例

type: json_type_boolean,json_type_double, json_type_int, json_type_object, json_type_array, json_type_string

void json_object_object_add(struct json_object* obj, char *key, struct json_object *val);

//添加个对象域到json对象中

参数

Obj – json对象

key – 域名字

val – json值对象

void json_object_object_del(struct json_object* obj, char *key);

//删除key值json对象

参数

obj – json对象

key – 域名字

int json_object_array_length(struct json_object *obj);

//得到json对象数组的长度

参数

ob j – json数组值对象


二、保活机制

音响作为客户端每隔5s向服务器发送一个数据包证明自己还活着

数据报json格式

5s使用闹钟函数alarm他可以在进程中设置一个定时器。他向进程发送SIGALRM信号。可以设置忽略或者不捕获此信号如果采用默认方式其动作是终止调用该alarm函数的进程。

所需头文件

#include<unistd.h>

函数原型

unsigned int alarmunsigned int seconds);

函数参数

seconds:指定秒数

函数返回值

成功如果调用此alarm前进程已经设置了闹钟时间则返回上一个闹钟时间的剩余时间否则返回0。

出错-1

在socket.c中设置

void *connect_cb(void *arg)
{
    int count = 5, ret;
    struct sockaddr_in server_addr;

    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = PF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    while (count--)
    {
        ret = connect(g_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (ret == -1)
        {
            sleep(5);
            continue;
        }
        
        //连接成功点亮 4 个LED灯
        led_on(0);
        led_on(1);
        led_on(2);
        led_on(3);

        alarm(TIMEOUT);
        signal(SIGALRM, send_server);

         break
}

调用send_server向服务器发送数据包

数据交互

  1. 保活

客户端{“status”“alive”}

socket.c

//5秒执行一次向服务器发送 alive 字符串
void send_server(int sig)
{
    struct json_object *json = json_object_new_object();//创建json对象
    
    json_object_object_add(json, "status", json_object_new_string("alive"));//添加保活键值
    json_object_object_add(json, "deviceid", json_object_new_string("001"));//设备id

    const char *buf = json_object_to_json_string(json);//将json格式转化为string对象
    int ret = send(g_sockfd, buf, strlen(buf), 0); //将json格式字符串发送给服务器
    if (-1 == ret)
    {
        perror("send");
    }
     1
    alarm(5);//循环调用一直发送保活
}

三、开始播放

2、开始播放

服务器发送{“cmd”“start”}

select.c改进

void m_select()
{
    show();

    fd_set tmpfd;
    int ret;
    char message[1024] = {0};//接收服务器消息

    while (1)
    {
        tmpfd = readfd;
        ret = select(g_maxfd + 1, &tmpfd, NULL, NULL, NULL);
        if (-1 == ret && errno != EINTR)
        {
            perror("select");
        }
        else if (-1 == ret && errno == EINTR)
        {
            continue;
        }

        if (FD_ISSET(g_sockfd, &tmpfd))           //TCP有数据可读
        {
            memset(message, 0, sizeof(message));//清空接收消息
            ret = recv(g_sockfd, message, sizeof(message), 0);//将服务器发送来的消息保存到message中
            if (-1 == ret)
            {
                perror("recv");
            }

            char cmd[64] = {0};
            parse_message(message, cmd);//解析服务器的数据放到cmd中
            if (!strcmp(cmd, "start"))//根据服务器不同的消息执行不同的功能
            {
                socket_start_play();            
            }
            else if (!strcmp(cmd, "stop"))
            {
                socket_stop_play();
            }
            else if (!strcmp(cmd, "suspend"))
            {
                socket_suspend_play();
            }
            else if (!strcmp(cmd, "continue"))
            {
                socket_continue_play();
            }
            else if (!strcmp(cmd, "prior"))
            {
                socket_prior_play();
            }
            else if (!strcmp(cmd, "next"))
            {
                socket_next_play();
            }
            else if (!strcmp(cmd, "voice_up"))
            {
                socket_voice_up_play();
            }
            else if (!strcmp(cmd, "voice_down"))
            {
                socket_voice_down_play();
            }
            else if (!strcmp(cmd, "sequence"))
            {
                socket_mode_play(SEQUENCEMODE);
            }
            else if (!strcmp(cmd, "random"))
            {
                socket_mode_play(RANDOM);
            }
            else if (!strcmp(cmd, "circle"))
            {
                socket_mode_play(CIRCLE);
            }
            else if (!strcmp(cmd, "get"))     //获取状态
            {    
                socket_get_status();
            }
            else if (!strcmp(cmd, "music"))   //获取所有音乐
            {
                socket_get_music();                                
            }
        }

按键按了app怎么同步

服务器每隔一秒获取播放器的状态

app上线获取所有音乐

get获取状态

music获取所有音乐

字符串转为json对象

void parse_message(const char *m, char *c)
{
    struct json_object *obj = json_tokener_parse(m);//将符合json格式的字符串构造为一个json对象

    struct json_object *json;
    //json_object_object_get_ex(obj, "cmd", &json);
    json = json_object_object_get(obj, "cmd");//从json中获取键cmd的值
    strcpy(c, json_object_get_string(json));将获取的值拷贝给c
}

player.h声明

#ifndef PLAYER_H
#define PLAYER_H

#include <unistd.h>

#define MUSICPATH   "/root/music_list/"

#define SHMKEY     1234
#define SHMSIZE    4096

#define SEQUENCEMODE    1
#define RANDOM          2
#define CIRCLE          3

//共享内存数据
struct shm
{
    int play_mode;
    char cur_name[64];
    pid_t ppid;
    pid_t child_pid;
    pid_t grand_pid;
};
typedef struct shm shm;

int InitShm();
void GetMusic();
void start_play();
void stop_play();
void suspend_play();
void continue_play();
void prior_play();
void next_play();
void voice_up();
void voice_down();
void set_mode(int mode);


#endif

socket.h

#ifndef SOCKET_H
#define SOCKET_H

#define SERVER_PORT   8000
#define SERVER_IP     "47.101.128.140"
//#define SERVER_IP    "127.0.0.1"
#define TIMEOUT       1

int InitSocket();
void socket_start_play();
void socket_stop_play();
void socket_suspend_play();
void socket_continue_play();
void socket_prior_play();
void socket_next_play();
void socket_voice_up_play();
void socket_voice_down_play();
void socket_mode_play(int);
void socket_get_status();
void socket_get_music();

#endif

开始播放回复一个消息给服务器

服务器发送{“cmd”“start”}

客户端回复{“result”“start_success”}

socket.c

void socket_start_play()//服务器调用开始播放
{
    start_play();//开始播放

    struct json_object *json = json_object_new_object(); //创建json对象
    json_object_object_add(json, "cmd", json_object_new_string("reply"));//向json对象添加cmd
    json_object_object_add(json, "result", json_object_new_string("start_success"));//添加result

    const char *buf = json_object_to_json_string(json);//转化为json对象
    int ret = send(g_sockfd, buf, strlen(buf), 0);//发送给服务器
    if (-1 == ret)
    {
        perror("send");
    }
}
void socket_stop_play()
{
    stop_play();

    struct json_object *json = json_object_new_object();
    json_object_object_add(json, "cmd", json_object_new_string("reply"));
    json_object_object_add(json, "result", json_object_new_string("stop_success"));

    const char *buf = json_object_to_json_string(json);
    int ret = send(g_sockfd, buf, strlen(buf), 0);
    if (-1 == ret)
    {
        perror("send");
    }
}

void socket_suspend_play()
{
    suspend_play();

    struct json_object *json = json_object_new_object();
    json_object_object_add(json, "cmd", json_object_new_string("reply"));
    json_object_object_add(json, "result", json_object_new_string("suspend_success"));

    const char *buf = json_object_to_json_string(json);
    int ret = send(g_sockfd, buf, strlen(buf), 0);
    if (-1 == ret)
    {
        perror("send");
    }
}

void socket_continue_play()
{
    continue_play();

    struct json_object *json = json_object_new_object();
    json_object_object_add(json, "cmd", json_object_new_string("reply"));
    json_object_object_add(json, "result", json_object_new_string("continue_success"));

    const char *buf = json_object_to_json_string(json);
    int ret = send(g_sockfd, buf, strlen(buf), 0);
    if (-1 == ret)
    {
        perror("send");
    }
}

void socket_prior_play()
{
    prior_play();

    struct json_object *json = json_object_new_object();
    json_object_object_add(json, "cmd", json_object_new_string("reply"));
    json_object_object_add(json, "result", json_object_new_string("success"));

    const char *buf = json_object_to_json_string(json);
    int ret = send(g_sockfd, buf, strlen(buf), 0);
    if (-1 == ret)
    {
        perror("send");
    }
}

void socket_next_play()
{
    next_play();

    struct json_object *json = json_object_new_object();
    json_object_object_add(json, "cmd", json_object_new_string("reply"));
    json_object_object_add(json, "result", json_object_new_string("success"));

    const char *buf = json_object_to_json_string(json);
    int ret = send(g_sockfd, buf, strlen(buf), 0);
    if (-1 == ret)
    {
        perror("send");
    }
}

void socket_mode_play(int mode)
{
    set_mode(mode);

    struct json_object *json = json_object_new_object();
    json_object_object_add(json, "cmd", json_object_new_string("reply"));
    json_object_object_add(json, "result", json_object_new_string("success"));

    const char *buf = json_object_to_json_string(json);
    int ret = send(g_sockfd, buf, strlen(buf), 0);
    if (-1 == ret)
    {
        perror("send");
    }
}



更新交换数据

socket.c

void send_server(int sig)
{
    struct json_object *json = json_object_new_object();
    json_object_object_add(json, "cmd", json_object_new_string("info"));
    json_object_object_add(json, "status", json_object_new_string("alive"));
    json_object_object_add(json, "deviceid", json_object_new_string("001"));

    const char *buf = json_object_to_json_string(json);
    int ret = send(g_sockfd, buf, strlen(buf), 0);
    if (-1 == ret)
    {
        perror("send");
    }

    alarm(5);
}

socket.c

void socket_get_status()
{
    //播放状态  当前歌曲名  音量
    struct json_object *json = json_object_new_object();
    json_object_object_add(json, "cmd", json_object_new_string("reply_status"));
    if (g_start_flag == 1 && g_suspend_flag == 0)
    {
        json_object_object_add(json, "status", json_object_new_string("start"));
    }
    else if (g_start_flag == 1 && g_suspend_flag == 1)
    {
        json_object_object_add(json, "status", json_object_new_string("suspend"));
    }
    else if (g_start_flag == 0)
    {
        json_object_object_add(json, "status", json_object_new_string("stop"));
    }
    json_object_object_add(json, "voice", json_object_new_int(iLeft));

    shm s;
    memset(&s, 0, sizeof(s));
    memcpy(&s, g_addr, sizeof(s));
    json_object_object_add(json, "music", json_object_new_string(s.cur_name));

    const char *buf = json_object_to_json_string(json);
    int ret = send(g_sockfd, buf, strlen(buf), 0);
    if (-1 == ret)
    {
        perror("send");
    }
}
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: 服务器