socket编程之温度实时监控上报(客户端)

一,首先是客户端需要实现的功能:

1, 树莓派上运行socket客户端程序,每隔30秒以字符串“ID/时间/温度”形式上报采样温度,其中ID为树莓派的编号,便于服 务器端区别是哪个树莓派客户端,如“RPI0001/2019-01-05 11:40:30/30.0C”;
2, 通过命令行参数指定服务器IP地址和端口以及间隔采样时间;
3, 程序放到后台运行,并通过syslog记录程序的运行出错、调试日志;
4, 程序能够捕捉kill信号正常退出;

二,客户端实现的流程图:

在这里插入图片描述

三 代码:

1,通过域名解析,将树莓派的域名解析成IP地址:

void print_usage(char *order)
{
        printf("%s usages:\n",order);
        printf("-I(IP):server IP\n");
        intf("-p(port):server port\n");
        printf("-h(help):help information\n");
        exit(0)}
int main(int argc,char **argv)
{
        char                   *serv_IP = NULL;
        int                    serv_port = 0;
        int                    opt;
        struct sockaddr_in     serv_addr;
        char                   buf[100];
        char                   buf1[100];
        char                   chip[20];
        int                    sockfd;
        int                    rv = -1;
        int                    on = 1;
        float                  temp;
        int                    line;
        struct timespec        tout;
        struct tm              *tmp;
        struct hostent         *hptr;
        struct option long_options[]=
        {
                
                {"IP",1,NULL,'i'},
                {"port",1,NULL,'p'},
                {"help",0,NULL,'h'},
                {0,0,0,0}
        
        };
          mylog(argv[0],__LINE__,DEBUG,"This is debug info");
          hptr = gethostbyname(argv[1]);
          if(hptr != NULL)
         {
              printf("domian name visit.\n");
               // printf("IP address1:%s\n",inet_ntoa(*(struct in_addr *)hptr->h_addr_list[1]));
              serv_IP = hptr->h_addr_list[1];
              printf("IP address2:%s\n",inet_ntoa(*(struct in_addr *)serv_IP));
        }
        else if(hptr == NULL)
        {
               switch(opt)
                   { 
                         case 'i':
                                serv_IP = optarg;
                                break;
                         case 'p':
                                serv_port = atoi(optarg);
                                break;
                         case 'h':
                                print_usage(argv[0]);
                                break;
                         default:
                                break}
        }
         if((!serv_IP)|(!serv_port))
                {
                     print_usage(argv[0]);
                }
     }

2socket函数初始化

 if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
        {
                printf("socket failed: %s\n",strerror(errno));
        }
          setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
        
        memset(&serv_addr,0,sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(serv_port);
        inet_aton(serv_IP,&serv_addr.sin_addr);

        memset(buf,0,sizeof(buf));
        
        printf("client is connecting serve...\n");
         
        if(connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
        {
                printf("connect failed: %s\n",strerror(errno));
          }
        else
        {        
                  printf("Connect successfully...\n");
         }
        

3while循环

while(1)
        {
                DS_get_tem(&temp,chip);
                tmp = localtime(&tout.tv_sec);
                strftime(buf1,sizeof(buf1),"%r",tmp);
                sprintf(buf,"%s %.3f鈩?%s",chip,temp,buf1);
                 
    if(write(sockfd,buf,strlen(buf)) <0 )
        {
                printf("write to serve unsuccessfully: %s\n",strerror(errno));
                goto cleanup;
          }
               
                memset(buf,0,sizeof(buf));
    if((rv = read(sockfd,buf,sizeof(buf))) < 0)
         {   
                 printf("read from serve unsuccessfully: %s\n",strerror(errno));
                 goto cleanup;
         }
     if(rv == 0)
         { 
                  printf("disconnect serve\n");
                  goto cleanup;
          }
                  printf(" %s\n",buf);
                  memset(buf,0,sizeof(buf));
                  sleep(10);      
           }
            close(sockfd);
         cleanup:
           close(sockfd);
           return 0
    }

            
          
                 

4 温度采样函数,该树莓派上的温度传感器ds18b20测量到的温度会通过字符串的形式被记录到一个特定的文件夹下面,文件内容会随着温度的变化而变化。这时我们需要用到Linux下文件I/O的相关操作去获取温度值。

void DS_get_tem(float *temp,char *chip)
{
        DIR                *dp;
        struct dirent      *dirp;
        char               w1_path[30] = "/sys/bus/w1/devices/";
        int                found = 0;
        int                fd;
        char               *ptr;
        char               buf[100];
        if((dp = opendir(w1_path)) < 0)
        {
                printf("opendir w1_path failed: %s\n",strerror(errno));
        }
  while((dirp = readdir(dp)) != NULL)
        {
                if(strstr(dirp->d_name,"28-") > 0)
                {
                        strcpy(chip,dirp->d_name);
                        found = 1;
                        break;
                }
        }
             closedir(dp);
             strncat(w1_path,chip,sizeof(w1_path));
             strncat(w1_path,"/w1_slave",sizeof(w1_path));
             
             if(!found)
        {
                printf("readdir failed and can't find %s\n",dirp->d_name);
        } 
             if((fd=open(w1_path,O_RDONLY)) < 0)
        {
                printf("open w1_path failed: %s\n",strerror(errno));
                close(fd);
        }
    
             if(read(fd,buf,sizeof(buf)) < 0)
        {
                printf("read from w1_path failed: %s\n",strerror(errno));
                close(fd);
        }
             ptr = strstr(buf,"t=");
        if(!ptr)
                printf("ERROR:can't get temperature\n");
                ptr+=2;
                *temp = atof(ptr)/1000;
}
        oid sig_kill(int signo)
{
        printf("SIGKILL[%d] caught\n",signo);
        exit(0);
}

源码:https://gitee.com/yangjianing1/test

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值