六、服务端开发
创始人
2024-05-22 04:03:59
0

服务器端开发:

服务器设计框架:

缓解和转发的作用

连接音箱和app

最大一个作用转发

一个app操作音箱

app绑定音箱

服务器类实现:

jsoncpp

libvent

verser.h

#ifndef SERVER_H
#define SERVER_H#include #define IP    "172.17.7.99"
#define PORT  8000class PlayerServer
{
private:struct event_base *base;             //事件集合public:PlayerServer(const char *ip = IP, int port = PORT);~PlayerServer();};#endif

vim server.cpp

#include "server.h"
//初始化构造函数
PlayerServer::PlayerServer(const char *ip, int port)
{base = event_base_new();               //创建事件集合struct sockaddr_in server_addr; //服务器ip绑定memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(port);server_addr.sin_addr.s_addr = inet_addr(ip);
//使用libventstruct evconnlistener *listener = evconnlistener_new_bind(base, listener_cb, base, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 10, (struct sockaddr *)&server_addr, sizeof(server_addr));if (NULL == listener){std::cout << "evconnlistener_new_bind error" << std::endl;}event_base_dispatch(base);      //监听集合
}PlayerServer::~PlayerServer()
{//释放两个对象evconnlistener_free(listener);event_base_free(base);
}

当有客户端发起连接的时候调用listener_cb回调函数

server.h

private:     //作为回调函数使用static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, 

server.cpp

void PlayerServer::listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int socklen, void *arg)
{struct event_base *base = (struct event_base *)arg;//事件集合作为参数传入std::cout << "有客户端连接 " << fd << std::endl;//创建bufferevent事件,客户端连接一个bev,app连接一个bev base事件集合, fd客户端描述符struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);if (NULL == bev){std::cout << "bufferevent_socket_new error" << std::endl;}bufferevent_setcb(bev, read_cb, NULL, event_cb, base);//调用两个回调函数,有读或者事件调用bufferevent_enable(bev, EV_READ);//使能bev
}

vim server.h

#ifndef SERVER_H
#define SERVER_H#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "player.h"
#include "node.h"#define IP    "172.17.7.99"
#define PORT  8000class PlayerServer
{
private:struct event_base *base;             //事件集合struct evconnlistener *listener;static Player *p;static std::list *l;public:PlayerServer(const char *ip = IP, int port = PORT);~PlayerServer();private:     //作为回调函数使用static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int socklen, void *arg);     static void read_cb(struct bufferevent *bev, void *ctx);static void event_cb(struct bufferevent *bev, short what, void *ctx);
};#endif

server.cpp

void PlayerServer::read_cb(struct bufferevent *bev, void *ctx)//当有客户端连接的可读时候调用该函数
{struct event_base *base = (struct event_base *)ctx;//事件集合作为参数传入char buf[1024] = {0};//接收数据size_t ret = bufferevent_read(bev, buf, sizeof(buf));//从客户端中读取数据if (ret < 0){std::cout << "bufferevent_read error" << std::endl;}
}void PlayerServer::event_cb(struct bufferevent *bev, short what, void *ctx)
{if (what & BEV_EVENT_EOF){std::cout << "音箱下线" << std::endl;}else {std::cout << "异常发生" << std::endl;}
}

在main.cpp创建服务器对象

#include "server.h"int main()
{PlayerServer ps;return 0;
}

服务器数据解析:

这里解析

解析消息

有可能app发过来

有可能音箱发过来

app向服务器发送

音箱向服务器发送

server.h

server.cpp

void PlayerServer::read_cb(struct bufferevent *bev, void *ctx)
{struct event_base *base = (struct event_base *)ctx;//事件集合char buf[1024] = {0};//保存客户端数据size_t ret = bufferevent_read(bev, buf, sizeof(buf));//读取客户端数据if (ret < 0){std::cout << "bufferevent_read error" << std::endl;}std::cout << buf << std::endl;Json::Reader reader; //解析jsonJson::Value val;bool result = reader.parse(buf, val);//解析val放到buf中if (!result){std::cout << "解析json出错" << std::endl;return;}char cmd[32] = {0};//获取cmd键值strcpy(cmd, val["cmd"].asString().c_str());//app发送的消息if (!strcmp(cmd, "bind"))                //绑定功能{Node n;//结构体n.app_bev = bev;//保存appbevstrcpy(n.app_id, val["appid"].asString().c_str());//获取appidstrcpy(n.device_id, val["deviceid"].asString().c_str());//获取设备idn.online_flag = 0;//设备是否在线,设备不在线n.app_online_flag = 1;//app是否在线,app在线l->push_back(n);//把结构体放入链表中//回复APPval["cmd"] = "bind_success";//回复app连接成功//把Value对象转换成stringstd::string str = Json::FastWriter().write(val);size_t ret = bufferevent_write(bev, str.c_str(), strlen(str.c_str()));//回复给appif (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}else if (!strcmp(cmd, "search_bind"))     //查询是否已经绑定{//遍历链表,判断链表中是否存在 appidstd::list::iterator it;for (it = l->begin(); it != l->end(); it++){if (!strcmp(it->app_id, val["appid"].asString().c_str())){it->app_bev = bev;           //更新 app_bevit->app_online_flag = 1;     //app在线//appid 存在val["cmd"] = "reply_bind";val["result"] = "yes";break;}}if (it == l->end())            //链表遍历到最后,appid 不存在{val["cmd"] = "reply_bind";val["result"] = "no";}std::string str = Json::FastWriter().write(val);size_t ret = bufferevent_write(bev, str.c_str(), strlen(str.c_str()));if (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}else if (!strcmp(cmd, "app_start"))      //开始播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_stop"))       //结束播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_suspend"))    //暂停播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_continue"))   //继续播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_prior"))      //上一首{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_next"))       //下一首{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_voice_up"))   //增加音量{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_voice_down")) //减小音量{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_sequence"))   //顺序播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_random"))     //随机播放{    p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_circle"))     //单曲播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_music"))      //获取音乐{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_off_line"))  //APP下线{for (std::list::iterator it = l->begin(); it != l->end(); it++){if (it->app_bev == bev){it->app_online_flag = 0;bufferevent_free(it->app_bev);std::cout << "APP下线" << std::endl;break;}}}//音箱发送的消息else if (!strcmp(cmd, "reply"))          //操作成功回复{p->player_reply_result(l, bev, val);}else if (!strcmp(cmd, "info"))           //音箱的保活消息{p->player_alive_info(l, bev, val, base);    }else if (!strcmp(cmd, "reply_status"))   //回复播放器状态{p->player_reply_result(l, bev, val);}else if (!strcmp(cmd, "reply_music"))      //返回所有音乐{p->player_reply_result(l, bev, val);}
}

node.h

#ifndef NODE_H
#define NODE_H#include 
#include 
#include struct Node 
{struct bufferevent *app_bev;struct bufferevent *device_bev;char app_id[8];char device_id[8];int online_flag;                     //表示设备是否在线  0 表示不在线int app_online_flag;                 //表示app 是否在线//time_t time;struct event timeout;                //定时器事件
};
typedef struct Node Node;struct timeout_node
{std::list *l;char id[8];
};
typedef struct timeout_node tNode;#endif

保活消息

vim player.h

vim player.cpp

判断device id在不在链表

player.h

#ifndef PLAYER_H
#define PLAYER_H#include 
#include "node.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include class Player
{
private:public:void player_alive_info(std::list *l, struct bufferevent *bev, Json::Value val, struct event_base *base);void player_operation(std::list *l, struct bufferevent *app_bev, const char *cmd);void player_reply_result(std::list *l, struct bufferevent *bev, Json::Value val);static void timeout_cb(evutil_socket_t fd, short event, void *arg);
};#endif

player.cpp

#include "player.h"void Player::player_alive_info(std::list *l, struct bufferevent *bev, Json::Value val, struct event_base *base)//保活调用
{char deviceid[8] = {0};//存放涉笔idstrcpy(deviceid, val["deviceid"].asString().c_str());//把客户端的deviceid拷贝到deviceid中//从链表中查找deviceidfor (std::list::iterator it = l->begin(); it != l->end(); it++){if (!strcmp(deviceid, it->device_id))    //比较deviceid是否在链表中{if (it->online_flag == 0)           //表示设备不在线,第一次发送保活消息{tNode *t = new tNode;t->l = l;strcpy(t->id, deviceid);event_assign(&(it->timeout), base, -1, EV_PERSIST, timeout_cb, t);    //设置事件参数struct timeval tv;evutil_timerclear(&tv);tv.tv_sec = 1;                  //1秒执行一次event_add(&(it->timeout), &tv);it->online_flag = 1;            //表示设备在线}it->device_bev = bev;it->time = time(NULL);std::cout << "收到保活消息 信息更新成功" << std::endl;return;}}std::cout << "收到保活消息 但是设备未绑定" << std::endl;
}

服务器处理app消息:

app发送开始结束等消息

服务器收到这些消息转发

player.cpp

/*
描述:服务器收到APP消息,转发给音箱
参数:app_bev 对应的是app的bufferevent
*/
void Player::player_operation(std::list *l, struct bufferevent *app_bev, const char *cmd)
{Json::Value val;if (!strcmp(cmd, "app_start")){val["cmd"] = "start";}else if (!strcmp(cmd, "app_stop")){val["cmd"] = "stop";}else if (!strcmp(cmd, "app_suspend")){val["cmd"] = "suspend";}else if (!strcmp(cmd, "app_continue")){val["cmd"] = "continue";}else if (!strcmp(cmd, "app_prior")){val["cmd"] = "prior";}else if (!strcmp(cmd, "app_next")){val["cmd"] = "next";}else if (!strcmp(cmd, "app_voice_up")){val["cmd"] = "voice_up";}else if (!strcmp(cmd, "app_voice_down")){val["cmd"] = "voice_down";}else if (!strcmp(cmd, "app_sequence")){val["cmd"] = "sequence";}else if (!strcmp(cmd, "app_random")){val["cmd"] = "random";}else if (!strcmp(cmd, "app_circle")){val["cmd"] = "circle";}else if (!strcmp(cmd, "app_music")){val["cmd"] = "music";}std::string str = Json::FastWriter().write(val);size_t ret;//遍历链表判断是否在线for (std::list::iterator it = l->begin(); it != l->end(); it++){if (it->app_bev == app_bev)    {if (it->online_flag == 1)      //在线{ret = bufferevent_write(it->device_bev, str.c_str(), strlen(str.c_str()));    if (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}else{Json::Value v;v["cmd"] = "app_reply";v["result"] = "off_line";std::string s = Json::FastWriter().write(v);ret = bufferevent_write(app_bev, s.c_str(), strlen(s.c_str()));    if (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}}break;}
}
/*
描述:收到音箱的回复消息,服务器回复APP
参数:bev 对应的是音箱的 bufferevent
*/
void Player::player_reply_result(std::list *l, struct bufferevent *bev, Json::Value val)
{    char cmd[32] = {0};strcpy(cmd, val["cmd"].asString().c_str());if (!strcmp(cmd, "reply")){val["cmd"] = "app_reply";}else if (!strcmp(cmd, "reply_music")){val["cmd"] = "app_reply_music";}else if (!strcmp(cmd, "reply_status")){val["cmd"] = "app_reply_status";}std::string str = Json::FastWriter().write(val);size_t ret;//遍历链表,找到 app 对应的 buffereventfor (std::list::iterator it = l->begin(); it != l->end(); it++){if (it->device_bev == bev){if (it->app_online_flag == 1){ret = bufferevent_write(it->app_bev, str.c_str(), strlen(str.c_str()));if (ret < 0){std::cout << "bufferevent_write" << std::endl;}}return;}}std::cout << "app 不存在" << std::endl;
}void Player::timeout_cb(evutil_socket_t fd, short event, void *arg)
{std::cout << "定时器事件" << std::endl;tNode t;memcpy(&t, arg, sizeof(tNode));//1、根据 time 判断音箱是否在线std::list::iterator it;for (it = (t.l)->begin(); it != (t.l)->end(); it++){if (!strcmp(it->device_id, t.id)){if (time(NULL) - it->time > 1){it->online_flag = 0;     //表示不在线}else {it->online_flag = 1;}break;}}//2、如果音箱和 APP 同时在线,则发起状态请求if (it->app_online_flag == 1 && it->online_flag == 1){Json::Value val;val["cmd"] = "get";std::string str = Json::FastWriter().write(val);size_t ret = bufferevent_write(it->device_bev, str.c_str(), strlen(str.c_str()));if (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}
}

服务器定时任务:

服务器每隔一秒向音响播放播放器状态:

服务器开始定时器

libevent里面有一个定时器任务

思路

所有app 和音响对应关系在链表里面

每个节点都加一个定时器事件

修改一下链表,struct event timeout

定时器不一定启动,音响下线关掉

音响上线,向服务器发送保活消息,第一次发送启动一个定时器,online——flag

vim player.cpp

保活

先判断在不在线,第一次发送保活消息,然后启动定时器。

静态成员函数不能调用非静态成员变量

因为着急春招,写的比较潦草,主要是为了找工作对项目有一个印象,不是很详细,代码自取如下

一、main.cpp

#include "server.h"int main()
{PlayerServer ps;return 0;
}

二、node.h

#ifndef NODE_H
#define NODE_H#include 
#include 
#include struct Node 
{struct bufferevent *app_bev;struct bufferevent *device_bev;char app_id[8];char device_id[8];int online_flag;                     //表示设备是否在线  0 表示不在线int app_online_flag;                 //表示app 是否在线//time_t time;struct event timeout;                //定时器事件
};
typedef struct Node Node;struct timeout_node
{std::list *l;char id[8];
};
typedef struct timeout_node tNode;#endif

三、player.cpp

#include "player.h"void Player::player_alive_info(std::list *l, struct bufferevent *bev, Json::Value val, struct event_base *base)
{char deviceid[8] = {0};strcpy(deviceid, val["deviceid"].asString().c_str());for (std::list::iterator it = l->begin(); it != l->end(); it++){if (!strcmp(deviceid, it->device_id))    {if (it->online_flag == 0)           //表示设备不在线,第一次发送保活消息{tNode *t = new tNode;t->l = l;strcpy(t->id, deviceid);event_assign(&(it->timeout), base, -1, EV_PERSIST, timeout_cb, t);    //设置事件参数struct timeval tv;evutil_timerclear(&tv);tv.tv_sec = 1;                  //1秒执行一次event_add(&(it->timeout), &tv);it->online_flag = 1;            //表示设备在线}it->device_bev = bev;it->time = time(NULL);std::cout << "收到保活消息 信息更新成功" << std::endl;return;}}std::cout << "收到保活消息 但是设备未绑定" << std::endl;
}/*
描述:服务器收到APP消息,转发给音箱
参数:app_bev 对应的是app的bufferevent
*/
void Player::player_operation(std::list *l, struct bufferevent *app_bev, const char *cmd)
{Json::Value val;if (!strcmp(cmd, "app_start")){val["cmd"] = "start";}else if (!strcmp(cmd, "app_stop")){val["cmd"] = "stop";}else if (!strcmp(cmd, "app_suspend")){val["cmd"] = "suspend";}else if (!strcmp(cmd, "app_continue")){val["cmd"] = "continue";}else if (!strcmp(cmd, "app_prior")){val["cmd"] = "prior";}else if (!strcmp(cmd, "app_next")){val["cmd"] = "next";}else if (!strcmp(cmd, "app_voice_up")){val["cmd"] = "voice_up";}else if (!strcmp(cmd, "app_voice_down")){val["cmd"] = "voice_down";}else if (!strcmp(cmd, "app_sequence")){val["cmd"] = "sequence";}else if (!strcmp(cmd, "app_random")){val["cmd"] = "random";}else if (!strcmp(cmd, "app_circle")){val["cmd"] = "circle";}else if (!strcmp(cmd, "app_music")){val["cmd"] = "music";}std::string str = Json::FastWriter().write(val);size_t ret;//遍历链表判断是否在线for (std::list::iterator it = l->begin(); it != l->end(); it++){if (it->app_bev == app_bev)    {if (it->online_flag == 1)      //在线{ret = bufferevent_write(it->device_bev, str.c_str(), strlen(str.c_str()));    if (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}else{Json::Value v;v["cmd"] = "app_reply";v["result"] = "off_line";std::string s = Json::FastWriter().write(v);ret = bufferevent_write(app_bev, s.c_str(), strlen(s.c_str()));    if (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}}break;}
}/*
描述:收到音箱的回复消息,服务器回复APP
参数:bev 对应的是音箱的 bufferevent
*/
void Player::player_reply_result(std::list *l, struct bufferevent *bev, Json::Value val)
{    char cmd[32] = {0};strcpy(cmd, val["cmd"].asString().c_str());if (!strcmp(cmd, "reply")){val["cmd"] = "app_reply";}else if (!strcmp(cmd, "reply_music")){val["cmd"] = "app_reply_music";}else if (!strcmp(cmd, "reply_status")){val["cmd"] = "app_reply_status";}std::string str = Json::FastWriter().write(val);size_t ret;//遍历链表,找到 app 对应的 buffereventfor (std::list::iterator it = l->begin(); it != l->end(); it++){if (it->device_bev == bev){if (it->app_online_flag == 1){ret = bufferevent_write(it->app_bev, str.c_str(), strlen(str.c_str()));if (ret < 0){std::cout << "bufferevent_write" << std::endl;}}return;}}std::cout << "app 不存在" << std::endl;
}void Player::timeout_cb(evutil_socket_t fd, short event, void *arg)
{std::cout << "定时器事件" << std::endl;tNode t;memcpy(&t, arg, sizeof(tNode));//1、根据 time 判断音箱是否在线std::list::iterator it;for (it = (t.l)->begin(); it != (t.l)->end(); it++){if (!strcmp(it->device_id, t.id)){if (time(NULL) - it->time > 1){it->online_flag = 0;     //表示不在线}else {it->online_flag = 1;}break;}}//2、如果音箱和 APP 同时在线,则发起状态请求if (it->app_online_flag == 1 && it->online_flag == 1){Json::Value val;val["cmd"] = "get";std::string str = Json::FastWriter().write(val);size_t ret = bufferevent_write(it->device_bev, str.c_str(), strlen(str.c_str()));if (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}
}

四、player.h

#ifndef PLAYER_H
#define PLAYER_H#include 
#include "node.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include class Player
{
private:public:void player_alive_info(std::list *l, struct bufferevent *bev, Json::Value val, struct event_base *base);void player_operation(std::list *l, struct bufferevent *app_bev, const char *cmd);void player_reply_result(std::list *l, struct bufferevent *bev, Json::Value val);static void timeout_cb(evutil_socket_t fd, short event, void *arg);
};#endif

五、server.cpp

#include "server.h"Player *PlayerServer::p = new Player();      //创建播放器对象
std::list *PlayerServer::l = new std::list();PlayerServer::PlayerServer(const char *ip, int port)
{base = event_base_new();               //创建事件集合struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(port);server_addr.sin_addr.s_addr = inet_addr(ip);listener = evconnlistener_new_bind(base, listener_cb, base, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 10, (struct sockaddr *)&server_addr, sizeof(server_addr));if (NULL == listener){std::cout << "evconnlistener_new_bind error" << std::endl;}event_base_dispatch(base);      //监听集合
}PlayerServer::~PlayerServer()
{//释放两个对象evconnlistener_free(listener);event_base_free(base);
}void PlayerServer::listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int socklen, void *arg)
{struct event_base *base = (struct event_base *)arg;std::cout << "有客户端连接 " << fd << std::endl;//创建bufferevent事件struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);if (NULL == bev){std::cout << "bufferevent_socket_new error" << std::endl;}bufferevent_setcb(bev, read_cb, NULL, event_cb, base);bufferevent_enable(bev, EV_READ);
}void PlayerServer::read_cb(struct bufferevent *bev, void *ctx)
{struct event_base *base = (struct event_base *)ctx;char buf[1024] = {0};size_t ret = bufferevent_read(bev, buf, sizeof(buf));if (ret < 0){std::cout << "bufferevent_read error" << std::endl;}std::cout << buf << std::endl;Json::Reader reader;Json::Value val;bool result = reader.parse(buf, val);if (!result){std::cout << "解析json出错" << std::endl;return;}char cmd[32] = {0};strcpy(cmd, val["cmd"].asString().c_str());//app发送的消息if (!strcmp(cmd, "bind"))                //绑定功能{Node n;n.app_bev = bev;strcpy(n.app_id, val["appid"].asString().c_str());strcpy(n.device_id, val["deviceid"].asString().c_str());n.online_flag = 0;n.app_online_flag = 1;l->push_back(n);//回复APPval["cmd"] = "bind_success";//把Value对象转换成stringstd::string str = Json::FastWriter().write(val);size_t ret = bufferevent_write(bev, str.c_str(), strlen(str.c_str()));if (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}else if (!strcmp(cmd, "search_bind"))     //查询是否已经绑定{//遍历链表,判断链表中是否存在 appidstd::list::iterator it;for (it = l->begin(); it != l->end(); it++){if (!strcmp(it->app_id, val["appid"].asString().c_str())){it->app_bev = bev;           //更新 app_bevit->app_online_flag = 1;     //app在线//appid 存在val["cmd"] = "reply_bind";val["result"] = "yes";break;}}if (it == l->end())            //链表遍历到最后,appid 不存在{val["cmd"] = "reply_bind";val["result"] = "no";}std::string str = Json::FastWriter().write(val);size_t ret = bufferevent_write(bev, str.c_str(), strlen(str.c_str()));if (ret < 0){std::cout << "bufferevent_write error" << std::endl;}}else if (!strcmp(cmd, "app_start"))      //开始播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_stop"))       //结束播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_suspend"))    //暂停播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_continue"))   //继续播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_prior"))      //上一首{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_next"))       //下一首{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_voice_up"))   //增加音量{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_voice_down")) //减小音量{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_sequence"))   //顺序播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_random"))     //随机播放{    p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_circle"))     //单曲播放{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_music"))      //获取音乐{p->player_operation(l, bev, cmd);}else if (!strcmp(cmd, "app_off_line"))  //APP下线{for (std::list::iterator it = l->begin(); it != l->end(); it++){if (it->app_bev == bev){it->app_online_flag = 0;bufferevent_free(it->app_bev);std::cout << "APP下线" << std::endl;break;}}}//音箱发送的消息else if (!strcmp(cmd, "reply"))          //操作成功回复{p->player_reply_result(l, bev, val);}else if (!strcmp(cmd, "info"))           //音箱的保活消息{p->player_alive_info(l, bev, val, base);    }else if (!strcmp(cmd, "reply_status"))   //回复播放器状态{p->player_reply_result(l, bev, val);}else if (!strcmp(cmd, "reply_music"))      //返回所有音乐{p->player_reply_result(l, bev, val);}
}void PlayerServer::event_cb(struct bufferevent *bev, short what, void *ctx)
{if (what & BEV_EVENT_EOF){for (std::list::iterator it = l->begin(); it != l->end(); it++){if (it->device_bev == bev){std::cout << "音箱下线" << std::endl;it->online_flag = 0;              //表示不在线event_del(&it->timeout);           //移除定时器return;}/*if (it->app_bev == bev){std::cout << "APP 下线" << std::endl;it->app_online_flag = 0;}*/}}else {std::cout << "异常发生" << std::endl;}
}

六、server.h

#ifndef SERVER_H
#define SERVER_H#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "player.h"
#include "node.h"#define IP    "172.17.7.99"
#define PORT  8000class PlayerServer
{
private:struct event_base *base;             //事件集合struct evconnlistener *listener;static Player *p;static std::list *l;public:PlayerServer(const char *ip = IP, int port = PORT);~PlayerServer();private:     //作为回调函数使用static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *addr, int socklen, void *arg);     static void read_cb(struct bufferevent *bev, void *ctx);static void event_cb(struct bufferevent *bev, short what, void *ctx);
};#endif

相关内容

热门资讯

非安卓10系统手机,探索非安卓... 你有没有想过,为什么有些人会选择非安卓10系统的手机呢?是不是觉得这有点奇怪?别急,今天就来带你一探...
手机图标制作安卓系统,手机图标... 你有没有想过,那些在手机屏幕上跳动的图标,其实都是精心设计出来的艺术品呢?没错,今天就要带你一探究竟...
安卓系统和鸿蒙系统谁大,谁才是... 你有没有想过,手机里的操作系统就像是一场无声的较量?今天,咱们就来聊聊这个话题:安卓系统和鸿蒙系统,...
bj40安卓系统,功能解析与使... 你有没有发现,最近你的BJ40越野车变得聪明多了?没错,它升级了安卓系统,简直就像给它装上了个智能大...
安卓系统硬件核心板,揭秘智能设... 你有没有想过,手机里的安卓系统其实就像是一个庞大的城市,而硬件核心板就是这座城市的核心区域?今天,就...
王者荣耀安卓系统转区ios系统... 你有没有想过,把你的王者荣耀账号从安卓系统转到iOS系统呢?这可不是一件小事,里面可是有大学问的哦!...
安卓系统的音游,节奏与音乐的完... 你有没有发现,手机里的游戏越来越好玩了?尤其是那些音游,简直让人停不下来!今天,就让我带你深入了解一...
安卓系统取消下方按键,探索全新... 你知道吗?最近安卓系统来了一次大变动,那就是取消了下方按键!这可真是让人眼前一亮,让我们一起来看看这...
安卓系统显示原理设置,从像素到... 你有没有发现,你的安卓手机屏幕上那些花花绿绿的图标和文字,其实背后有着一套神奇而又复杂的显示原理呢?...
平板安卓4.0系统下载,平板下... 你有没有想过,拥有一台运行着最新安卓4.0系统的平板电脑,那感觉简直就像拥有了未来的钥匙?想象流畅的...
安卓原生12系统下载,原生系统... 你有没有听说?安卓原生12系统终于来了!这款全新的操作系统,不仅带来了全新的视觉体验,还有一堆实用的...
安卓怎么下泼辣系统,安卓设备轻... 你有没有想过给你的安卓手机来个“大变身”?想象你的手机瞬间变成了一个泼辣的“女侠”,不仅个性十足,而...
安卓版小米系统下载,畅享智能生... 你有没有发现,最近手机圈里又掀起了一股热潮?没错,就是安卓版小米系统的下载。这款系统自从推出以来,就...
提取安卓系统自带软件,探索安卓... 你有没有想过,你的安卓手机里那些看似不起眼的自带软件,其实都是隐藏的宝藏呢?今天,就让我带你一探究竟...
安卓系统投屏到鸿蒙系统,鸿蒙系... 亲爱的读者们,你是否有过这样的体验:手里拿着安卓手机,却想在大屏幕的鸿蒙系统设备上展示内容?别急,今...
sony 电视安卓8.0系统,... 亲爱的读者们,你是否也和我一样,对科技产品有着浓厚的兴趣呢?今天,我要和你聊聊一个让我眼前一亮的话题...
安卓 替换系统下载,探索安卓系... 你有没有想过,你的安卓手机其实可以换换口味呢?没错,就是那个一直默默陪伴你的系统,今天就来带你一起探...
安卓系统证书信任,安卓系统证书... 你有没有遇到过这种情况?手机里突然弹出一个提示,告诉你某个应用需要获取系统证书信任,然后你一脸懵逼,...
安卓系统应用数据目录,揭秘系统... 你有没有想过,你的安卓手机里那些应用,它们的数据都藏在哪个角落呢?今天,就让我带你一探究竟,揭开安卓...
kindle 安卓 系统 刷机... 亲爱的读者们,你是不是也和我一样,对电子阅读设备情有独钟?尤其是那款小巧便携的Kindle,简直是阅...