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