socket温度上报练习
通过读取文件“t=”后的内容/1000得到实时温度
文件io操作:
//读取温度值
int get_temper(float *temp,FILE *fp) //FILE参数用于记录日志
{
int fd;
char *ptr;
int rd;
char buf[1024];
char file_path[50] = TPATH;
DIR *dirp;
struct dirent *direntp;
int found = -1;
char chip[20];
dirp=opendir(file_path);
if(dirp==NULL)
{
fprintf(fp,"打开文件夹失败:%s",strerror(errno));
goto cleanup;
}
while((direntp=readdir(dirp))!=NULL) //循环遍历文件夹名字,找到“28-”文件夹
{
if(strstr(direntp->d_name,"28-"))
{
strcpy(chip,direntp->d_name);
found=1;
break;
}
}
strcat(file_path,chip);
strcat(file_path,"/w1_slave");
fd=open(file_path,O_RDONLY,644);
if(fd<0)
{
fprintf(fp,"打开文件失败:%s\n",strerror(errno));
return -1;
}
rd=read(fd,buf,sizeof(buf));
close(fd);
ptr=strstr(buf,"t=");
ptr+=2;
*temp=(atof(ptr)/1000.0);
cleanup:
closedir(dirp);
if(!found)
{
fprintf(fp,"找不到设备\n");
}
return 0;
}
socket上报,涉及域名解析,参数解析:(关于gethostbyname()函数详细点击)
int get_parameter(int argc,char **argv,int *port,char *ip)
{
char *_argv[argc];
int optret = 0;
char ipArry[1024];
for(int i=0;i<argc;i++)
_argv[i] = *(argv+i);
while((optret =getopt(argc,_argv,"i:p:"))!=-1)
{
switch(optret)
{
case 'i':
if(get_ip(optarg,ipArry)<0)
strncpy(ip,optarg,sizeof(ipArry));
strncpy(ip,ipArry,sizeof(ipArry));
break;
case 'p':
*port = atoi(optarg);
break;
default:
printf("输入格式:./client -p [port] -i [ip or hostname]\n");
break;
}
}
if(*port==0||*ip==0)
return -1;
return 1;
}
int get_ip(char *hostname,char *buf)
{
char *ipaddr = NULL;
struct hostent *gethost;
gethost = gethostbyname(hostname);
char ip[100];
if (NULL == gethost)
{
return -1;
}
memset(ip,0,sizeof(ip));
ipaddr = (char *)inet_ntop(gethost->h_addrtype,gethost->h_addr_list[0],ip,sizeof(ip));
strncpy(buf,ipaddr,sizeof(ip));
return 0;
}
要求程序在Linux后台运行,使用deamon()函数创建守护进程,守护进程需要自己的日志系统记录程序运行情况:
FILE *my_syslog(char *buf)
{
FILE *fp;
mode_t mode = umask(0);
if(access("./log/",F_OK)==0)
goto um;
if(mkdir("./log/",0755)<0)
{
printf("创建日志文件夹失败:%s\n",strerror(errno));
return NULL;
}
um:
umask(mode);
fp = fopen(SYSLOG,"a+");
if(NULL==fp)
printf("打开日志文件失败:%s\n",strerror(errno));
if(setvbuf(fp,buf,_IOLBF,128)!=0)
return NULL;
return fp;
}
void my_syslog_close(FILE *fp)
{
fprintf(fp,"关闭日志文件!\n");
fclose(fp);
}
socket上报,需要了解socket相关知识
//服务器连接
int connect_server (char *ip,int port,FILE *fp)
{
int sockfd = -1;
struct sockaddr_in cli_addr;
sockfd = socket(AF_INET,SOCK_STREAM,0);
if (sockfd < 0)
{
fprintf(fp,"socket初始化失败:%s\n",strerror(errno));
return -1;
}
memset(&cli_addr,0,sizeof(cli_addr));
cli_addr.sin_family= AF_INET;
cli_addr.sin_port = htons((uint16_t)(port));
inet_aton(ip,&cli_addr.sin_addr);
fprintf(fp,"准备连接%s\n端口%d\n",ip,port);
if ((connect(sockfd,(struct sockaddr *)&cli_addr,sizeof(cli_addr))) < 0)
{
fprintf(fp,"连接到:%s 端口:%d 失败:%s\n",ip,port,strerror(errno));
return -1;
}
return sockfd;
}
、、
由于是多个c文件编写,需要了解程序编译过程这篇博客可以借鉴点击
编写makefile文件可以:
a. 管理代码的编译,决定该编译什么文件,编译顺序,以及是否需要重新编译;
b. 节省编译时间。如果文件有更改,只需重新编译此文件即可,无需重新编译整个工程;
c. 一劳永逸。Makefile通常只需编写一次,后期就不用过多更改。
本次程序结构并不是很复杂,我的makefile:
src = $(wildcard ./*.c)
obj = $(patsubst %.c,%.o,$(src))
target = client
CC = gcc
$(target):$(obj)
@$(CC) $(obj) -o $(target) -Wall
%.o:%.c
@$(CC) -c $< -o $@
clean:
@rm -rf *.o
完整代码在github站点存放点击查看