linux智能家居中控程序

可以借鉴一下程序的思路

main.c

#include "DB/inc/db_user.h"
#include "DB/inc/db_message.h"
#include "net/inc/socket_core.h"
#include "userControl.h"

extern struct ServerClass serverClass;
void serverStop(void);
void serverStart(void);
void serverEntry(void);
void serverExit(void);
void receiveClose(void);

// 用户处理函数
void msgReceive(char *buff, int *psize);  //接受到数据报时响应,其中buff和size为数据报到内存首地址和长度
void clientBody(void *connfd);      // 客户机连接上的处理主函数,其中connfd为连接符
void *sendHandle(void *arg);  //客户机发送线程函数
int msgSend(void *arg);         // 客户机发送处理函数,由userControl.ifRespond=TRUE触发,将userControl.p打包发送

//数据库连接符
struct DB db;
struct DB_User db_user;
struct DB_Message db_message;

extern struct UserControl userControl;

int main(){

  serverClass.stop = serverStop;
  serverClass.start= serverStart;
  serverClass.entry= serverEntry;
  serverClass.Exit = serverExit;
  serverClass.body = clientBody;
  serverClass.receiveEvent = msgReceive;
  serverClass.closeEvent = receiveClose;
  serverClass.run();
  return 0;
}
/*
 * @function: 线程接收消息函数
 * 服务器接收到客户发来的数据报时触发
 * @psize: 返回实际接收到的数据报字节数
 * @buff: 接收数据的临时缓冲
 */
void msgReceive(char *buff, int *psize){

  printf("触发消息接收函数... ...\n");
  char user[20];
  char passwd[20];
  int num;
  printf("receive size:%d\n", *psize);
  struct Package *pack = (struct Package *)buff;
  struct Package tempPack;
  printf("Pack Type:%s\n", pack->type);
  if (strcmp(pack->type, "") == 0)  //type为空,数据传输有问题
  {
      printf("接收数据格式有问题\n");
      return ;
  }
  //客户机请求类别
  if (strcmp(pack->type, TP_LOAD) == 0){    //登陆请求
      //验证用户名和密码是否正确,若正确则给登陆成功应答
      if (pack->data == NULL)    //数据传输有问题
      {
          printf("接收数据格式有问题\n");
          return ;
      }
      strcpy(user, pack->data[0].fromuser);
      strcpy(passwd, pack->data[0].passwd);
          printf("user:%s,passwd:%s\n", user, passwd);

      printf("用户登陆验证中... ...\n");
      if ((num = db_user.checkUser(&db, user, passwd)) >= 0){
          printf("用户%s登陆验证成功\n", user);
          //设置用户登陆在线
          onLoad(user, TRUE);

          if ((num = db_user.setUserState(&db, user, TRUE)) >= 0){
              printf("User %s Load\n", user);
          }
          //设置应答缓冲
          strcpy(tempPack.type, TP_ACK_LOAD);
          strcpy(tempPack.msg, "load success");
          tempPack.success = TRUE;
          tempPack.len = 0;
          setPackage(&tempPack);
      }else{
          //登陆失败
          printf("用户%s登陆验证失败\n", user);
          //设置应答缓冲
          //设置应答缓冲
          strcpy(tempPack.type, TP_ACK_LOAD);
          tempPack.len = 0;
          strcpy(tempPack.msg, "fail to load");
          tempPack.success = FALSE;
          setPackage(&tempPack);
      }
      respond();
  }else if (strcmp(pack->type, TP_REFRESH) == 0){ //刷新请求
      printf("用户刷新请求... ... \n");
      // 互斥锁加锁
      pthread_mutex_lock(&userControl.mutex);
      printf("加锁********************\n");
      if (strcmp(userControl.user, "") == 0 || userControl.ifLoad == FALSE)  //用户名为空或者未登陆
      {
          printf("未登录,无法刷新... ...\n");
          // 互斥锁解锁
          pthread_mutex_unlock(&userControl.mutex);
          printf("解锁********************\n");
          goto QUIT;
      }
      // 互斥锁解锁
      pthread_mutex_unlock(&userControl.mutex);
      printf("解锁********************\n");
      int device_num = pack->len;
      int ifRefresh = 0;    //0表示刷新成功,其他值表示刷新失败的设备编号

      printf("用户正在刷新... ...%d\n", device_num);
      //获取客户机发过来的数据包进行刷新
      struct Message msg;
      int i = 0;
      for (i=0;i<(device_num);i++)
      {
          printf("正在尝试刷新第%d个设备\n",i);
          strcpy(msg.fromuser, pack->data[i].fromuser);
          strcpy(msg.touser, pack->data[i].touser);
          strcpy(msg.data, pack->data[i].data);
          strcpy(msg.state, pack->data[i].state);
          if ((num = db_message.setMessage(db_message.db, msg)) >= 0){
              printf("成功刷新设备%s\n这是第%d个设备\n",pack->data[i].data, i);
              continue;
          }
          printf("刷新失败,错误码:%d ... ...\n", num);
          ifRefresh = i;  //刷新失败的设备
      }
      //应答
      if (ifRefresh == 0) // 刷新成功
      {
          strcpy(tempPack.type, TP_ACK_REFRESH);
          tempPack.len = 0;
          strcpy(tempPack.msg, "success to refresh");
          tempPack.success = TRUE;
          setPackage(&tempPack);
          printf("刷新成功\n");
      }else{              //刷新失败,返回刷新失败的设备编号
          strcpy(tempPack.type, TP_ACK_REFRESH);
          strcpy(tempPack.msg, "fail to refresh");
          tempPack.success = FALSE;
          tempPack.len = 0;
          setPackage(&tempPack);
          printf("刷新失败\n");
      }
      respond();

  }else if(strcmp(pack->type, TP_CONTROL) == 0){    //控制请求
      printf("控制请求... ... \n");
      // 互斥锁加锁
      pthread_mutex_lock(&userControl.mutex);
      printf("加锁********************\n");
      if (strcmp(userControl.user, "") == 0 || userControl.ifLoad == FALSE)  //用户名为空或者未登陆
      {
          printf("未登录,无法请求控制... ...\n");
          // 互斥锁解锁
          pthread_mutex_unlock(&userControl.mutex);
          printf("解锁********************\n");
          goto QUIT;
      }
      strcpy(user, userControl.user);
      // 互斥锁解锁
      pthread_mutex_unlock(&userControl.mutex);
      printf("解锁********************\n");

      struct Message msg[MSG_SIZE];
      int num;
      if ((num = db_message.getMessage(db_message.db, user, msg, MSG_SIZE)) < 0){
          printf("获取控制数据失败%d\n", num);
          goto QUIT;
      }
      printf("总共%d个设备\n准备控制发送... ...", num);
      // 加锁
      int i = 0;
      pthread_mutex_lock(&userControl.mutex);
      printf("加锁********************\n");
      for (i=0;i<num;i++)
      {
          strcpy(userControl.p.type, TP_ACK_CONTROL); // 设置为应答类型
          strcpy(userControl.p.msg, "control");
          userControl.p.success = TRUE;  //错误
          userControl.p.len = num;       //msg长度
          strcpy(userControl.p.data[i].fromuser,msg[i].fromuser);
          strcpy(userControl.p.data[i].touser,msg[i].touser);
          strcpy(userControl.p.data[i].data,msg[i].data);
          strcpy(userControl.p.data[i].state,msg[i].state);
      }
      // 解锁
      pthread_mutex_unlock(&userControl.mutex);
      printf("解锁********************\n");
      respond();

  }else{    //未知请求
      strcpy(tempPack.type, TP_ACK_UNDEFINED);
      strcpy(tempPack.msg, "unknown type");
      tempPack.success = FALSE;
      tempPack.len = 0;
      setPackage(&tempPack);
      respond();
  }

QUIT:
  return ;
}
/*
 * @function: 客户端连接主处理线程
 * 客户机连接后完成初始化等操作后的主处理线程函数
 * @arg: 为客户机连接成功的网络连接符
 */
void clientBody(void *arg){
  printf("进入客户连接主处理线程... ...\n");
  int connfd = *((int*)arg);
  void *status;
  pthread_t wpid;
  pthread_create(&wpid, NULL, &sendHandle, &connfd);    // 发送消息线程
  pthread_join(wpid, &status);  // 等待线程退出
  printf("退出客户连接主处理线程... ...\n");
  return ;
}
/*
 * @function: 客户端主线程函数分离出来的线程
 * 主要是为了msgSend的触发作用做环境搭建
 * @arg: 为客户机连接成功的网络描述符
 */
void *sendHandle(void *arg){
  printf("启动发送线程... ...\n");
  while(1){
      // 加锁
      pthread_mutex_lock(&userControl.cond_mutex);
      printf("加变量锁**********************\n");
      while (userControl.ifRespond == FALSE)    // 条件为假则休眠等待
      {
          pthread_cond_wait(&userControl.cond, &userControl.cond_mutex);
      }
      // 条件为真触发执行msgSend后,修改条件变量ifRespond

      if (msgSend(arg) < 0 || userControl.ifExit == 1)  //userControl.ifExit是当receive接收到-1退出时触发这个也退出
      {
          userControl.ifRespond = FALSE;
          // 解锁
          pthread_mutex_unlock(&userControl.cond_mutex);
          printf("解变量锁*****************\n");
          break;
      }
      userControl.ifRespond = FALSE;
      // 解锁
      pthread_mutex_unlock(&userControl.cond_mutex);
      printf("解变量锁**************************\n");
  }
  printf("退出发送线程... ...\n");
  return 0;
}
/*
 * @function: 发送消息
 *  设置条件变量userControl.ifRespond=TRUE时触发
 *  触发后将会按照userControl.len长度,将userContro.p的数据报进行格式打包并发送
 * @ret: 返回值负值时结束整个发送监听线程,userControl.ifRespond触发功能失效
 */
int msgSend(void *arg){

    int connfd = *((int *)arg);
    sleep(1);  //延时1s才发送
    pthread_mutex_lock(&userControl.mutex);
    printf("加锁********************\n");
    char *buff = (char *)&userControl.p;
    pthread_mutex_unlock(&userControl.mutex);
    printf("解锁********************\n");

    int size = sizeof(struct Package)+userControl.p.len*(sizeof(struct MSG))-MSG_SIZE*(sizeof(struct MSG));

    printf("发送数据 -----------\n");

    size = write(connfd, buff, size);
    printf("ret:%d\n",size);
    return size;
}
/*
 * @function: 服务器启动时运行
 */
void serverStart(void){
  printf("启动服务器... ...\n");
  // TODO将用户在线状态全部清0,服务器启动后用户还未连接是不在线的
}
void serverStop(void){
  printf("关闭服务器... ...\n");
}
void serverEntry(void){
  printf("新客户机连接... ...!\n");
  db_init(&db);        //初始化db
  db.open(&db.conn);   //打开db
  db_user_init(&db_user, &db); //初始化user_db
  db_message_init(&db_message, &db); //初始化user_db
  // 初始化数据库连接符还有用户控制结构体等客户连接全局变量
  // 初始化互斥锁
  if (pthread_mutex_init(&userControl.mutex, NULL))
  {
      printf("初始化互斥锁失败\n");
      exit(1);
  }
  // 初始化条件变量互斥锁
  if (pthread_mutex_init(&userControl.cond_mutex, NULL))
  {
      printf("初始化条件互斥锁失败\n");
      exit(1);
  }
  // 初始化条件变量
  if (pthread_cond_init(&userControl.cond, NULL))
  {
      printf("初始化条件变量失败\n");
      exit(1);
  }
  // 互斥锁加锁
 // pthread_mutex_lock(&userControl.mutex);
  strcpy(userControl.user,""); 
  userControl.ifLoad = FALSE;    //用户不在线
  userControl.ifRespond = FALSE; //不用应答客户机
  userControl.ifExit = 0;
  // 互斥锁解锁
 // pthread_mutex_unlock(&userControl.mutex);
}
void serverExit(void){
  char temp[20];
  printf("客户机退出连接!\n");
  //设置用户不在线
  int num;
  // 互斥锁加锁
 // pthread_mutex_lock(&userControl.mutex);
  strcpy(temp, userControl.user);
  //互斥锁解锁
 // pthread_mutex_unlock(&userControl.mutex);
  if (strcmp(temp, "") == 0)  //fromuser为空,用户没登陆
  {
      goto QUIT;
  }
  if ((num = db_user.setUserState(&db, temp, FALSE)) >= 0){
     printf("Set User UnLoad Success:%d\n", num);
  }

  //释放数据库连接符还有用户控制结构体等客户连接全局变量
QUIT:
  // 释放互斥锁
  pthread_mutex_destroy(&userControl.mutex);
  printf("释放锁********************\n");
  // 释放条件变量互斥锁
  pthread_mutex_destroy(&userControl.cond_mutex);
  printf("释放条件锁*******************\n");
  // 释放条件变量
  pthread_cond_destroy(&userControl.cond);
  printf("释放条件变量***************\n");
  userControl.ifExit = 0;
  db.close(&db.conn);  //释放数据库连接符
}
void receiveClose(void){
    printf("接收连接线程断开... ...\n");
    //触发body退出
    pthread_mutex_lock(&userControl.cond_mutex);
    printf("加变量锁************************\n");
    if (userControl.ifRespond == FALSE)
    {
        pthread_cond_signal(&userControl.cond);
    }
    userControl.ifRespond = TRUE;
    userControl.ifExit = 1;
    pthread_mutex_unlock(&userControl.cond_mutex);
    printf("解变量锁************************\n");
}

usercontrol.h



#include "userControl.h"

struct UserControl userControl;

void onLoad(char user[], int ifLoad){
    pthread_mutex_lock(&userControl.mutex);
    printf("加锁************************\n");
    strcpy(userControl.user, user);
    userControl.ifLoad = ifLoad;
    pthread_mutex_unlock(&userControl.mutex);
    printf("解锁************************\n");
}
void setPackage(struct Package *pack){
    pthread_mutex_lock(&userControl.mutex);
    printf("加锁************************\n");
    strcpy(userControl.p.type, pack->type);
    strcpy(userControl.p.msg, pack->msg);
    userControl.p.success = pack->success;
    userControl.p.len = pack->len;
    memcpy(userControl.p.data, pack->data, pack->len*(sizeof(struct MSG)));
    pthread_mutex_unlock(&userControl.mutex);
    printf("解锁************************\n");
}
void getPackage(struct Package *pack){
    pthread_mutex_lock(&userControl.mutex);
    printf("加锁************************\n");
    strcpy(pack->type, userControl.p.type);
    strcpy(pack->msg, userControl.p.msg);
    pack->success = userControl.p.success;
    pack->len = userControl.p.len;
    memcpy(pack->data, userControl.p.data, userControl.p.len*(sizeof(struct MSG)));
    pthread_mutex_unlock(&userControl.mutex);
    printf("解锁************************\n");
}
void respond(){
    pthread_mutex_lock(&userControl.cond_mutex);
    printf("加变量锁************************\n");
    if (userControl.ifRespond == FALSE)
    {
        pthread_cond_signal(&userControl.cond);
    }
    userControl.ifRespond = TRUE;
    pthread_mutex_unlock(&userControl.cond_mutex);
    printf("解变量锁************************\n");
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值