赞
踩
这一模块的思路和前面的语言控制模块很相似,差别只是调用TCP 去控制
废话少说,放码过来
- #include <pthread.h>
-
- #include "socket_interface.h"
- #include "control.h"
- #include "socket.h"
- #include "mq_queue.h"
- #include "global.h"
- #include <netinet/tcp.h> // 设置 tcp 心跳 的参数
-
- static int s_fd = -1;
-
- static int tcpsocket_init(void)
- {
- s_fd = socket_init(IPADDR,IPPORT);
- //return s_fd;
- return -1;
- }
-
- static void tcpsocket_final(void)
- {
- close(s_fd);
- s_fd = -1;
- }
-
- static void* tcpsocket_get(void *arg)
- {
-
- int c_fd = -1;
- unsigned char buffer[BUF_SIZE];
- int ret = -1;
- struct sockaddr_in c_addr;
- mqd_t mqd = -1;
- ctrl_info_t * ctrl_info = NULL;
- int keepalive = 1; // 开启TCP_KEEPALIVE选项
- int keepidle = 10; // 设置探测时间间隔为10秒
- int keepinterval = 5; // 设置探测包发送间隔为5秒
- int keepcount = 3; // 设置探测包发送次数为3次
-
-
-
- pthread_detach(pthread_self()); // 和主线程(他的父线程)分离
-
- printf("%s|%s|%d s_fd = %d\n", __FILE__, __func__, __LINE__, s_fd);
-
- if(-1 == s_fd) // 判断是否初始化成功
- {
- s_fd = tcpsocket_init();
- if(-1 == s_fd)
- {
- printf("tcpsocket_init error\n");
- pthread_exit(0);
- }
-
- }
-
- if(NULL != arg)
- ctrl_info = (ctrl_info_t*)arg;
- if(NULL != ctrl_info)
- mqd = ctrl_info->mqd;
-
-
- if((mqd_t)-1 == mqd)
- {
- pthread_exit(0);
- }
-
- memset(&c_addr, 0, sizeof(struct sockaddr_in));
-
- int clen = sizeof(struct sockaddr_in);
-
- printf("%s thread start\n", __func__);
- while (1) // 一直等待接收
- {
- c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &clen); // 获得新的客户端 描述符
-
- if (c_fd == -1)
- {
- continue;
- }
-
- ret = setsockopt(c_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive,sizeof(keepalive));
- if(-1 == ret){
- perror("setsockopt");
- break;
- }
-
- ret = setsockopt(c_fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(keepidle));
- if(-1 == ret){
- perror("setsockopt");
- break;
- }
- ret = setsockopt(c_fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepinterval,
- sizeof(keepinterval));
- if(-1 == ret){
- perror("setsockopt");
- break;
- }
- ret = setsockopt(c_fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcount,
- sizeof(keepcount));
- if(-1 == ret){
- perror("setsockopt");
- break;
- }
-
- // 打印调试信息
- printf("%s | %s | %d: Access a connection from %s:%d\n", __FILE__, __func__, __LINE__, inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port));
-
-
-
- while (1)
- {
- memset(buffer, 0, BUF_SIZE);
- ret = recv(c_fd, buffer, BUF_SIZE, 0); // 等待接收
- // 将接收到数据打印出来
- printf("%s|%s|%d, 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",__FILE__,__func__,__LINE__,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]);
-
- if (ret > 0)
- {
- if(buffer[0] == 0xAA && buffer[1] == 0x55
- &&buffer[4]==0x55 && buffer[5]==0xAA)
- {
- printf("%s|%s|%d, send: 0x%x,0x%x,0x%x,0x%x,0x%x,0x%x\n",__FILE__,__func__,__LINE__,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]);
-
- send_msg(mqd,buffer,ret);
- }
-
- }
- else if (0 == ret || -1 == ret) // 没读到,or 读到空
- {
- break;
- }
- }
-
-
- }
-
- pthread_exit(0);
-
- }
-
-
- struct control tcpsocket_control ={
- .control_name = "tcpsocket",
- .init = tcpsocket_init,
- .final = tcpsocket_final,
- .get = tcpsocket_get,
- .set = NULL, //不需要实现 设置
- .next = NULL
- };
-
-
- struct control *add_tcpsocket_to_ctrl_list(struct control *phead)
- {
- //头插法实现 添加链表节点
- struct control *pnew = NULL;
-
-
- if(NULL == phead)
- {
- phead = &tcpsocket_control; // 直接传入我们的 voice_control
- }
-
- else// 头结点非空 - 链表有数据
- {
- tcpsocket_control.next = phead; //把新的节点的next指向头结点
- phead = &tcpsocket_control; // 让心节点成为头结点
- }
-
- return phead;
-
- };
-
-
-
-
-
-
-
-
-
-
-
-
- #ifndef ___SOCKET_INTERFACE_H___
- #define ___SOCKET_INTERFACE_H___
-
- #include "control.h"
- struct control *add_tcpsocket_to_ctrl_list(struct control *phead);
-
-
-
- #endif
- #include <stdio.h>
- #include <pthread.h>
- #include <stdlib.h>
-
- #include "control.h"
- #include "mq_queue.h"
- #include "voice_interface.h"
- #include "socket_interface.h"
- #include "global.h"
-
- // msg_queue_create
-
-
-
- int main() {
- pthread_t thread_id;
- struct control *control_phead = NULL;
- struct control *pointer = NULL;
- ctrl_info_t *ctrl_info = NULL;
- ctrl_info = (ctrl_info_t *)malloc(sizeof(ctrl_info_t));
- ctrl_info->ctrl_phead = NULL;
- ctrl_info->mqd = -1;
-
- int node_num = 0; // 统计节点数
-
- // 创建消息队列
- ctrl_info->mqd = msg_queue_create();
- if(-1 == ctrl_info->mqd)// 创建消息队列失败
- {
- printf("%s|%s|%d, mqd= %d\n",__FILE__,__func__,__LINE__,ctrl_info->mqd);
- return -1;
- }
-
- ctrl_info->ctrl_phead = add_voice_to_ctrl_list(ctrl_info->ctrl_phead);
- ctrl_info->ctrl_phead = add_tcpsocket_to_ctrl_list(ctrl_info->ctrl_phead);
- //ctrl_info->ctrl_phead = add_fire_to_ctrl_list(ctrl_info->ctrl_phead);
-
-
- pointer = ctrl_info->ctrl_phead;
-
- while(NULL!=pointer) // 对所有控制结构体初始化,并且统计节点数
- {
- if(NULL != pointer->init)
- {
- printf("%s|%s|%d control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);
- pointer->init();
- }
- pointer = pointer->next;
- node_num++; // 统计节点数
- }
-
- // 根据节点的总数 --> 创建对应数目的线程
- pthread_t *tid = (pthread_t *)malloc(sizeof(int) *node_num);
- pointer = ctrl_info->ctrl_phead;
-
- for(int i=0;i<node_num;++i)//遍历所有节点
- {
- if(NULL != pointer->get){
- printf("%s|%s|%d control_name = %s\n",__FILE__,__func__,__LINE__,pointer->control_name);
- pthread_create(&tid[i],NULL,(void *)pointer->get,(void *)ctrl_info); // 传入这个结构体参数,方便同时调用多组线程里面的API
- }
- pointer = pointer->next;
- }
-
- for(int i=0;i<node_num;++i)
- {
- pthread_join(tid[i],NULL);
- }
-
- for(int i=0;i<node_num;++i)
- {
- if(NULL != pointer->final)
- pointer->final(); // 接打开的使用接口关闭
- pointer = pointer->next;
- }
-
- msq_queue_final(ctrl_info->mqd);
-
- }
make
scp ./obj/smarthome orangepi@192.168.1.11:/home/orangepi
sudo -E ./smarthome
scp: /home/orangepi/smarthome: Text file busy
kill -9 进程即可
kill之后成功了
bind: Address already in use
要解决这个问题,您可以尝试以下步骤:
查找并关闭现有进程:使用 netstat
、lsof
或 ss
命令来查找正在监听该端口的进程,并关闭它。
- sudo netstat -tulnp | grep [端口号]
- # 或者
- sudo lsof -i :[端口号]
- # 或者
- sudo ss -tulnp | grep [端口号]
找到进程ID(PID)后,使用 kill -9
命令来结束该进程。
重启计算机:如果无法确定哪个进程正在使用端口,或者无法结束该进程,您可以考虑重启计算机。
使用不同的端口:如果您只是想要快速测试您的应用程序,并且不关心特定的端口号,您可以尝试使用另一个端口。
(注意发送格式 16进制)
否则你发送的数据很可能变成这样
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。