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

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) ——语音识别控制(线程)

猜你喜欢

转载自blog.csdn.net/lcx1837/article/details/113956835