智能家居 ——网络服务器线程控制

Posted 行稳方能走远

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了智能家居 ——网络服务器线程控制相关的知识,希望对你有一定的参考价值。

网络线程控制代码

inputCommand.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;										//存放文件描述符(串口/网络)
	int (*Init)(struct Command *file);			//“初始化”函数指针
	int s_fd;									//存放服务器套接字描述符
	char ipAdress[32];							//存放 IP地址
	char port[12];								//存放端口号
	int (*getCommand)(struct Command *cmd);		//“获取指令”函数指针

	struct Command *next;
};

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

mainPro.c

#include <stdio.h>
#include <string.h>
#include "inputCommand.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 = addSocketControlToCommandLink(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);			//创建“读取端口”线程 连接一个客户端就去对接 可接纳10个客户端
	}
}

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;
}

socketControl.c

#include "inputCommand.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.0.19",				    //树莓派 IP地址
	.port = "8088",								//打开的端口号
};

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 *addSocketControlToCommandLink(struct Command *phead)		//“网络控制”(对象)加入指令链表函数
{
	if(phead == NULL){
		return &socketControl;
	}else{
		socketControl.next = phead;
		phead = &socketControl;
		return phead;
	}
}

代码测试

手机下载网络调试助手,和树莓派连入同一个WIFI,输入树莓派IP地址以及端口号,发送消息:Today is 520,树莓派接收消息成功。

在这里插入图片描述

在这里插入图片描述

往期文章

智能家居 (1) ——智能家居整体功能框架
智能家居 (2) ——设计模式的引入
智能家居 (3) ——工厂模式继电器控制灯
智能家居 (4) ——工厂模式火焰报警
智能家居 (5) —— LD3320语音模块二次开发
智能家居 (6) ——语音识别线程控制
智能家居 (7) ——网络服务器线程控制
智能家居 (8) ——智能家居项目整合(网络控制线程、语音控制线程,火灾报警线程)
网络编程知识预备(1) ——了解OSI网络模型
网络编程知识预备(2) ——浅显易懂的三次握手与四次挥手
网络编程知识预备(3) ——SOCKET、TCP、HTTP之间的区别与联系
网络编程知识预备(4) ——了解HTTP协议与HTTPS协议
网络编程知识预备(5) ——libcurl库简介及其编程使用
智能家居 (9) ——人脸识别摄像头安装实现监控功能
智能家居 (10) ——人脸识别祥云平台编程使用
智能家居 (11) ——树莓派摄像头捕捉人脸并识别
智能家居 (12) ——人脸识别整合到智能家居系统
智能家居 (13) ——智能家居加入手机app端控制

以上是关于智能家居 ——网络服务器线程控制的主要内容,如果未能解决你的问题,请参考以下文章

智能家居 ——语音识别线程控制

JMeter:逻辑控制器_模块控制器(Module Controller)

JMeter接口测试-模块控制器

多个用户访问同一段代码

智能家居系统-框架设计

MySQL系列:kafka停止命令