六、服务端开发
创始人
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

相关内容

热门资讯

安卓子系统windows11,... 你知道吗?最近科技圈可是炸开了锅,因为安卓子系统在Windows 11上的兼容性成了大家热议的话题。...
电脑里怎么下载安卓系统,电脑端... 你有没有想过,你的电脑里也能装上安卓系统呢?没错,就是那个让你手机不离手的安卓!今天,就让我来带你一...
索尼相机魔改安卓系统,魔改系统... 你知道吗?最近在摄影圈里掀起了一股热潮,那就是索尼相机魔改安卓系统。这可不是一般的改装,而是让这些专...
安卓系统哪家的最流畅,安卓系统... 你有没有想过,为什么你的手机有时候像蜗牛一样慢吞吞的,而别人的手机却能像风一样快?这背后,其实就是安...
安卓最新系统4.42,深度解析... 你有没有发现,你的安卓手机最近是不是有点儿不一样了?没错,就是那个一直在默默更新的安卓最新系统4.4...
android和安卓什么系统最... 你有没有想过,你的安卓手机到底是用的是什么系统呢?是不是有时候觉得手机卡顿,运行缓慢,其实跟这个系统...
平板装安卓xp系统好,探索复古... 你有没有想过,把安卓系统装到平板上,再配上XP系统,这会是怎样一番景象呢?想象一边享受着安卓的便捷,...
投影仪装安卓系统,开启智能投影... 你有没有想过,家里的老式投影仪也能焕发第二春呢?没错,就是那个曾经陪你熬夜看电影的“老伙计”,现在它...
安卓系统无线车载carplay... 你有没有想过,开车的时候也能享受到苹果设备的便利呢?没错,就是那个让你在日常生活中离不开的iOS系统...
谷歌安卓8系统包,系统包解析与... 你有没有发现,手机更新换代的速度简直就像坐上了火箭呢?这不,最近谷歌又发布了安卓8系统包,听说这个新...
微软平板下软件安卓系统,开启全... 你有没有想过,在微软平板上也能畅享安卓系统的乐趣呢?没错,这就是今天我要跟你分享的神奇故事。想象你手...
coloros是基于安卓系统吗... 你有没有想过,手机里的那个色彩斑斓的界面,背后其实有着一个有趣的故事呢?没错,我要说的就是Color...
安卓神盾系统应用市场,一站式智... 你有没有发现,手机里的安卓神盾系统应用市场最近可是火得一塌糊涂啊!这不,我就来给你好好扒一扒,看看这...
黑莓平板安卓系统升级,解锁无限... 亲爱的读者们,你是否还记得那个曾经风靡一时的黑莓手机?那个标志性的全键盘,那个独特的黑莓体验,如今它...
安卓文件系统采用华为,探索高效... 你知道吗?最近安卓系统在文件管理上可是有了大动作呢!华为这个科技巨头,竟然悄悄地给安卓文件系统来了个...
深度系统能用安卓app,探索智... 你知道吗?现在科技的发展真是让人惊叹不已!今天,我要给你揭秘一个超级酷炫的话题——深度系统能用安卓a...
安卓系统的分区类型,深度解析存... 你有没有发现,你的安卓手机里藏着不少秘密?没错,就是那些神秘的分区类型。今天,就让我带你一探究竟,揭...
安卓系统铠无法兑换,揭秘无法兑... 最近是不是有很多小伙伴在玩安卓系统的游戏,突然发现了一个让人头疼的问题——铠无法兑换!别急,今天就来...
汽车安卓系统崩溃怎么刷,一键刷... 亲爱的车主朋友们,你是否曾遇到过汽车安卓系统崩溃的尴尬时刻?手机系统崩溃还能重启,但汽车系统崩溃了,...
miui系统可以刷安卓p系统吗... 亲爱的手机控们,你是否对MIUI系统情有独钟,同时又对安卓P系统的新鲜功能垂涎欲滴?今天,就让我带你...