智能家居 (4) ——网络控制(线程)

   日期:2021-02-25     浏览:107    评论:0    
核心提示:目录1.工厂模式创建远程网络控制对象:(1)socketControl.c 文件(网络远程控制)(2)command.h 文件(指令方式类)2.多线程控制——远程网络控制(调试):(1)main.c 文件(主函数)1.工厂模式创建远程网络控制对象:(1)socketControl.c 文件(网络远程控制)(2)command.h 文件(指令方式类)2.多线程控制——远程网络控制(调试):(1)main.c 文件(主函数)...

目录

    • 1.工厂模式创建网络控制对象:
        • (1)socketControl.c 文件(网络控制)
        • (2)command.h 文件(指令方式类)
    • 2.多线程控制——网络控制(调试):
        • (1)main.c 文件(主函数)
        • (2)调试
    • 3.往期文章:

1.工厂模式创建网络控制对象:

(1)socketControl.c 文件(网络控制)

#include "command.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>


int socketControlInit(struct Command *file);						//“网络控制”功能初始化函数声明
struct Command *addSocketControlToLink(struct Command *phead);		//“网络控制”(对象)加入指令链表函数声明


struct Command socketControl = { 				//定义“网络控制”对象
	.commandName = "socketControl",				//名字
	.command = { '\0'},							//初始化储存“指令”的空间
	.Init = socketControlInit,					//指定“网络控制”功能初始化函数
	.ipAdress = "192.168.137.110",				//树莓派 IP地址
	.port = "8888",								//打开的端口号
};

int socketControlInit(struct Command *file)
{ 
	int s_fd;											//套接字描述符
	struct sockaddr_in s_addr;
	memset(&s_addr,0,sizeof(struct sockaddr_in));

	s_fd = socket(AF_INET,SOCK_STREAM,0);				//创建套接字
    if(s_fd == -1){ 										//若创建套接字失败
            perror("socketControl error");
            exit(-1);
    }

	s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(atoi(file->port));
    inet_aton(file->ipAdress,&s_addr.sin_addr);
	if(bind(s_fd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in)) == -1){ 		//套接字与端口号绑定
    	perror("bind error");
    	exit(-1);
    }

	if(listen(s_fd,10) == -1){ 							//打开监听
    	perror("listen error");
    	exit(-1);
    }

	file->s_fd = s_fd;									//发送套接字描述符
}

struct Command *addSocketControlToLink(struct Command *phead)		//“网络控制”(对象)加入指令链表函数
{ 
	if(phead == NULL){ 
		return &socketControl;
	}else{ 
		socketControl.next = phead;
		phead = &socketControl;
		return phead;
	}
}

(2)command.h 文件(指令方式类)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiringPi.h>
#include <wiringSerial.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


struct Command
{ 
	char commandName[128];						//“控制方式”名
	char deviceFilesName[128];					//存放初始化所需文件的路径
	char command[32];							//存放指令
	int fd;										//存放文件描述符
	void (*Init)(struct Command *file);			//“初始化”函数指针
	int s_fd;									//存放套接字描述符
	char ipAdress[32];							//存放 IP地址
	char port[12];								//存放端口号
	int (*getCommand)(struct Command *cmd);		//“获取指令”函数指针

	struct Command *next;
};

struct Command *addSocketControlToLink(struct Command *phead);		//“网络控制”加入指令链表函数声明

2.多线程控制——网络控制(调试):

(1)main.c 文件(主函数)

仅调试

#include <stdio.h>
#include <string.h>
#include "equipment.h"
#include "command.h"
#include <pthread.h>
#include <unistd.h>

struct Command *findCommandByName(char *name,struct Command *phead);		//寻找链节函数声明
void *socketControlThread(void *data);			//“网络控制”线程函数声明
void *socketReadThread(void *data);				//“读取端口”线程函数声明

struct Command *cmdhead = NULL;					//创建“指令”链表全局变量
struct Command *socketHandler = NULL;			//创建“链节处理”全局变量

int main()
{ 
	cmdhead = addSocketControlToLink(cmdhead);		//“网络控制”对象加入链表

	pthread_t socketControl_thread;
	pthread_create(&socketControl_thread,NULL,socketControlThread,NULL);	//创建“网络控制”线程

	pthread_join(socketControl_thread, NULL);		//主函数等待“网络控制”线程退出
	return 0;
}

void *socketControlThread(void *data)				//“网络控制”线程
{ 
	int c_fd;											//文件描述符
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof(struct sockaddr_in));
	socklen_t clen = sizeof(struct sockaddr_in);
	pthread_t socketRead_thread;						//存放线程 ID


	socketHandler = findCommandByName("socketControl",cmdhead);			//寻找并返回“网络控制”所处链节
	if(socketHandler == NULL){ 											//若找不到
		printf("find socketHandler error\n");
		pthread_exit(NULL);
	}
	if(socketHandler->Init(socketHandler) < 0){ 							//执行“网络控制”功能初始化函数
		printf("socketControl init error\n");
		pthread_exit(NULL);
	}


	while(1){ 
		c_fd = accept(socketHandler->s_fd,(struct sockaddr*)&c_addr,&clen);		//接收连接请求
		socketHandler->fd = c_fd;												//发送文件描述符

		pthread_create(&socketRead_thread,NULL,socketReadThread,NULL);			//创建“读取端口”线程
	}
}

void *socketReadThread(void *data)				//“读取端口”线程
{ 
	int nread;
	memset(socketHandler->command,'\0',sizeof(socketHandler->command));		//每次读取前,清空 “command(存放指令)”
	nread = read(socketHandler->fd,socketHandler->command,sizeof(socketHandler->command));		//读取并存放到 “command”
	if(nread == 0){ 
		printf("No command received\n");
	}else{ 
		printf("Get command:%s\n",socketHandler->command);			//读取成功,打印数据
	}
}

struct Command *findCommandByName(char *name,struct Command *phead)			//通过“名字”寻找链节函数
{ 
	struct Command *tmp = phead;

	if(phead == NULL){ 
		return NULL;
	}

	while(tmp != NULL){ 
		if(strcmp(name,tmp->commandName) == 0){ 
			return tmp;
		}
		tmp = tmp->next;
	}
	return NULL;
}

(2)调试

工具:NetAssist

①选择相应选项:
(协议类型)
(树莓派 IP 地址)
(打开监听的端口号)

②树莓派运行调试函数:

③点击连接,并发送内容Hello

树莓派终端:

④点击断开,再次连接,并发送内容HAHAHAHA

树莓派终端:

3.往期文章:

智能家居 (1) ——工厂模式继电器控制灯
智能家居 (2) ——工厂模式火焰报警器
智能家居 (3) ——语音识别控制(线程)

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服