基于树莓派/香橙派的智能家居项目(2、1 输入部分(socket编程))

文章介绍了如何使用Socket编程实现TCP传输,通过手机APP或小程序接收用户指令,控制设备。定义了一个结构体`InputCommander`来存储相关数据,并初始化socket连接。当有客户端接入时,创建子线程处理通信,接收到命令后进行解析并作出响应。为提高效率,使用`sleep`函数释放资源。

前言:这部分将会是外接信号的输入部分,现在主要的信号收入可以采用手机app(或者小程序)进行控制,语音控制,或者实体的按键控制。在此结合先前学习的socket编程,将采用tcp传输的方式,由客户端传输指令进行控制。

查看具体抽象出来的结构体如下:

struct InputCommander
{
	char comName[128];
	char devName[128];
	char command[32];
	char port[12];
	int sfd;
	int fd;
	int (*init)(struct InputCommander* comstr, char *ipAdress, char* port);
	int (*getCommand)(struct InputCommander* comstr);	
	char log[1024];
	struct InputCommander* next;
};

如上有些变量不一定会用到,为了适应多个输入单元,以及保持代码整体的简洁性,若有其他需要可自行修改添加。

对于socket编程,需要用到的变量可以是:comName字符串,用于该结构体的检索;socket编程需要用到的端口号ip地址等等。以及初始化程序、指令的获取程序。

socket初始化程序:

int socketColInit(struct InputCommander* socketMes, char *ipAdress, char* port)
{
	int sockfd;
	struct sockaddr_in s_addr;
	
	memset(&s_addr,0,sizeof(struct sockaddr_in));

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
		perror("socket");
		return -1;
	}

	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(socketMes->port));

	inet_aton("192.168.3.113",&s_addr.sin_addr);

	if(bind(sockfd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)) == -1){
		perror("bind");
		return -1;
	}

	listen(sockfd, 10);
	printf("listening .......\n");

	socketMes->sfd = sockfd;
	
	return sockfd;
}

上述就是socket编程的基本流程,不多赘述。

对于每一个输入单元,我都将创建于一个线程,下面是具体的线程执行函数:

void* socketHandler(void* datas)
{
	int socket_fd;
	int c_fd;
	int n_read = 0;
	pid_t pid;	

	struct sockaddr_in c_addr;

	int size = sizeof(struct sockaddr_in);
	
	memset(&c_addr, 0, size);

	socketStr = findInputName("socket", pheadCom);
	if(socketStr == NULL)
		pthread_exit(NULL);
	
	socket_fd = socketStr->init(socketStr, NULL, NULL);
	if(socket_fd == -1)
		pthread_exit(NULL);
	
	while(1)
	{
		if((c_fd = accept(socket_fd, (struct sockaddr *)&c_addr, &size)) == -1)
		{
			perror("accept\n");
			pthread_exit(NULL);
		}
		
		socketStr->fd = c_fd;
		printf("%s:connect success\n", inet_ntoa(c_addr.sin_addr));

		pid = fork();
		if(pid == -1)
		{
			perror("fork:\n");
		}
		else if(pid == 0)
		{
			while(1)
			{				
				memset(socketStr->command, '\0', sizeof(socketStr->command));
				n_read = socketStr->getCommand(socketStr);

				if(n_read > 0)
				{
					socketLitCrl(socketStr->command);
				}

				if(n_read == 0){
					printf("quit\n");
					break;
				}
								
				sleep(1);
			}
		}
	}
}

为了执行的高效性,当检测到有客户端接入后,会开辟一个子进程,进行对应的处理,socketLitCrl函数就只是对于相对应的字符串进行识别,后续补充。每当检测到有指令收到做出相对应的识别即可,当有客户端退出后,结束相应进程。

为避免该线程长时间占用资源,使用sleep函数主动让出资源。

总结:这部分只是socket编程的基本步骤,连接即可。只需一次识别做出判断,也没有必要对于这部分过程进行”上锁“。如有其他需要可自行添加。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值