FreeRTOS Lwip Socket APi TCP Server 1对多
源文件
/********************************************************************************* @file lwip_tcp_driver.cpp* @brief TCP Server implementation using LwIP******************************************************************************* @attention* @author by syf*******************************************************************************/#include "lwip_tcp_driver.h"
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include <cstring> // For memsetstatic const char send_data[8] = {0xff,0x44,0x55,0x66,0xdd};namespace lwip_tcp {struct client_info *client_fo;
struct client_task_info *client_task_fo;
struct link_socket_info *socket_link_info;// 发送数据的任务
void send_task(void *param) {struct client_info* client = (struct client_info *)param;const char *data_to_send = "Hello, Client!";int data_length = strlen(data_to_send);while (1) {// 发送数据到客户端int sent_bytes = send(client->socket_num, data_to_send, data_length, 0);if (sent_bytes < 0) {debug_print("Failed to send data to client[%d]\r\n", client->socket_num);break; // 如果发送失败,退出循环}debug_print("Sent %d bytes to client[%d]\r\n", sent_bytes, client->socket_num);vTaskDelay(1000 / portTICK_PERIOD_MS); // 延迟1秒}// 如果退出循环,释放客户端信息并删除任务mem_free(client);closesocket(client->socket_num);vTaskDelete(NULL);
}void tcp_server_thread(void *param){struct client_info* client = (struct client_info *)param;/* 某个客户端连接 */debug_print("Client[%d]%s:%d is connect server\r\n", client->socket_num, inet_ntoa(client->ip_addr.sin_addr),ntohs(client->ip_addr.sin_port));/* 向客户端发送连接成功信息 */send(client->socket_num, (const void* )send_data, strlen(send_data), 0);// 创建发送任务TaskHandle_t send_task_handle;xTaskCreate(send_task, "SendTask", 1024, (void *)client, osPriorityNormal, &send_task_handle);if (send_task_handle == NULL) {debug_print("Failed to create send task for client[%d]\r\n", client->socket_num);}while (1){char str[1024];memset(str, 0, sizeof(str));int bytes = recv(client->socket_num, str, sizeof(str), 0);/* 获取关闭连接的请求 */if (bytes <= 0){mem_free(client);closesocket(client->socket_num);break;}debug_print("[%d] %s:%d recv size:%d\r\n", client->socket_num, inet_ntoa(client->ip_addr.sin_addr),ntohs(client->ip_addr.sin_port), bytes);send((int )client->socket_num, (const void * )str, bytes, 0);}debug_print("[%d]%s:%d is disconnect...\r\n", client->socket_num, inet_ntoa(client->ip_addr.sin_addr),ntohs(client->ip_addr.sin_port));vTaskDelete(NULL); /* 删除该任务 */
}void tcp_server_init(void){int sin_size = sizeof(struct sockaddr_in);char client_name[10] = "server";char client_num[10];/* socket连接结构体申请内存 */socket_link_info = (struct link_socket_info *)mem_malloc(sizeof(struct link_socket_info));/* 设置客户端任务信息 */client_task_fo = (struct client_task_info *)mem_malloc(sizeof(struct client_task_info));client_task_fo->client_handler = NULL;client_task_fo->client_task_pro = osPriorityNormal;client_task_fo->client_task_stk = 1024; //无法运行时增大栈内存/* 创建socket连接 */if((socket_link_info->sock_listen = socket(AF_INET, SOCK_STREAM, 0)) == -1){debug_print("Socket error\r\n");return;}/* 初始化连接的服务端地址 */socket_link_info->listen_addr.sin_family = AF_INET;socket_link_info->listen_addr.sin_port = htons(5000);socket_link_info->listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);memset(&(socket_link_info->listen_addr.sin_zero), 0, sizeof(socket_link_info->listen_addr.sin_zero));/* 绑定socket和连接的服务端地址信息 */if (bind(socket_link_info->sock_listen, (struct sockaddr * )&socket_link_info->listen_addr, sizeof(struct sockaddr)) < 0){debug_print("Bind fail!\r\n");goto __exit;}/* 监听客户端的数量 */listen(socket_link_info->sock_listen, 4);debug_print("begin listing...\r\n");while (1){/* 请求客户端连接 */socket_link_info->sock_connect = accept(socket_link_info->sock_listen, (struct sockaddr* )&socket_link_info->connect_addr, (socklen_t* )&sin_size);if (socket_link_info->sock_connect == -1){debug_print("no socket,waitting others socket disconnect.\r\n");continue;}lwip_itoa((char *)socket_link_info->sock_connect, (size_t)client_num, 10);strcat(client_name, client_num);client_task_fo->client_name = client_name;client_task_fo->client_num = client_num;/* 初始化连接客户端信息 */client_fo = (struct client_info *)mem_malloc(sizeof(struct client_info));client_fo->socket_num = socket_link_info->sock_connect;memcpy(&client_fo->ip_addr, &socket_link_info->connect_addr, sizeof(struct sockaddr_in));client_fo->sockaddr_len = sin_size;/* 创建连接的客户端任务 */xTaskCreate((TaskFunction_t )tcp_server_thread, (const char * )client_task_fo->client_name,(uint16_t )client_task_fo->client_task_stk,(void * )(void*) client_fo,(UBaseType_t )client_task_fo->client_task_pro ++ ,(TaskHandle_t * )&client_task_fo->client_handler);if (client_task_fo->client_handler == NULL){debug_print("no memery for thread %s startup failed!\r\n",client_task_fo->client_name);mem_free(client_fo);continue;}else{debug_print("thread %s success!\r\n", client_task_fo->client_name);}}__exit: debug_print("listener failed\r\n");/* 关闭这个socket */closesocket(socket_link_info->sock_listen);vTaskDelete(NULL); /* 删除本任务 */
}} // lwip_tcp namespace end
头文件
/********************************************************************************* @file lwip_tcp_driver.h* @brief ******************************************************************************* @attention* @auther by shiyongfu*******************************************************************************/
#ifndef LWIP_TCP_DRIVER_H
#define LWIP_TCP_DRIVER_H#include "stm32f4xx_hal.h"
#include "lwip/opt.h"
#include "lwip/sockets.h"#include "lwip/sys.h"
#include "lwip/api.h"namespace lwip_tcp{/* 客户端的信息 */struct client_info{int socket_num; /* socket号的数量 */struct sockaddr_in ip_addr; /* socket客户端的IP地址 */int sockaddr_len; /* socketaddr的长度 */};/* 客户端的任务信息 */struct client_task_info{UBaseType_t client_task_pro; /* 客户端任务优先级 */uint16_t client_task_stk; /* 客户端任务优先级 */TaskHandle_t * client_handler; /* 客户端任务控制块 */char *client_name; /* 客户端任务名称 */char *client_num; /* 客户端任务数量 */};/* socket信息 */struct link_socket_info{int sock_listen; /* 监听 */int sock_connect; /* 连接 */struct sockaddr_in listen_addr; /* 监听地址 */struct sockaddr_in connect_addr;/* 连接地址 */};void tcp_server_init(void);void tcp_client_init(void);
}
#endif
相关文章:
FreeRTOS Lwip Socket APi TCP Server 1对多
源文件 /********************************************************************************* file lwip_tcp_driver.cpp* brief TCP Server implementation using LwIP******************************************************************************* at…...
逆袭之路(11)——python网络爬虫:原理、应用、风险与应对策略
困厄铸剑心,逆袭展锋芒。 寒苦凝壮志,腾跃绘华章。 我要逆袭。 目录 一、引言 二、网络爬虫的基本原理 (一)网络请求与响应 (二)网页解析 (三)爬行策略 三、网络爬虫的应用领…...
KOI技术-事件驱动编程(Sping后端)
1 “你日渐平庸,甘于平庸,将继续平庸。”——《以自己喜欢的方式过一生》 2. “总是有人要赢的,那为什么不能是我呢?”——科比布莱恩特 3. “你那么憎恨那些人,和他们斗了那么久,最终却要变得和他们一样,…...
LVS 负载均衡原理 | 配置示例
注:本文为 “ LVS 负载均衡原理 | 配置” 相关文章合辑。 部分内容已过时,可以看看原理实现。 未整理去重。 使用 LVS 实现负载均衡原理及安装配置详解 posted on 2017-02-12 14:35 肖邦 linux 负载均衡集群是 load balance 集群的简写,翻…...
Hive分区再分桶表
在Hive中,数据通常是根据分区(partition)来组织的,但是对于大数据集,单层分区可能不够用,因此可以进一步细分为桶(bucket)。桶可以用于提供额外的并行处理和优化查询性能。在这种情况…...
从 Coding (Jenkinsfile) 到 Docker:全流程自动化部署 Spring Boot 实战指南(简化篇)
前言 本文记录使用 Coding (以 Jenkinsfile 为核心) 和 Docker 部署 Springboot 项目的过程,分享设置细节和一些注意问题。 1. 配置服务器环境 在实施此过程前,确保服务器已配置好 Docker、MySQL 和 Redis,可参考下列链接进行操作࿱…...
Linux官文转载-- Linux 内核代码风格
Warning 此文件的目的是为让中文读者更容易阅读和理解,而不是作为一个分支。 因此, 如果您对此文件有任何意见或更新,请先尝试更新原始英文文件。 这是一个简短的文档,描述了 linux 内核的首选代码风格。代码风格是因人而异的&a…...
Qt监控系统放大招/历经十几年迭代完善/多屏幕辅屏预览/多层级设备树/网络登录和回放
一、前言说明 近期对视频监控系统做了比较大的更新升级,主要就是三点,第一点就是增加了辅屏预览,这个也是好多个客户需要的功能,海康的iVMS-4200客户端就有这个功能,方便在多个屏幕打开不同的视频进行查看,…...
【贪心算法】贪心算法七
贪心算法七 1.整数替换2.俄罗斯套娃信封问题3.可被三整除的最大和4.距离相等的条形码5.重构字符串 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃…...
LangChain教程 - 表达式语言 (LCEL) -构建智能链
系列文章索引 LangChain教程 - 系列文章 LangChain提供了一种灵活且强大的表达式语言 (LangChain Expression Language, LCEL),用于创建复杂的逻辑链。通过将不同的可运行对象组合起来,LCEL可以实现顺序链、嵌套链、并行链、路由以及动态构建等高级功能…...
使用Locust对Redis进行负载测试
1.安装环境 安装redis brew install redis 开启redis服务 brew services start redis 停止redis服务 brew services stop redis 安装Python库 pip install locust redis 2.编写脚本 loadTest.py # codingutf-8 import json import random import time import redis …...
HIVE数据仓库分层
1:为什么要分层 大多数情况下,我们完成的数据体系却是依赖复杂、层级混乱的。在不知不觉的情况下,我们可能会做出一套表依赖结构混乱,甚至出现循环依赖的数据体系。 我们需要一套行之有效的数据组织和管理方法来让我们的数据体系…...
数据结构与算法之动态规划: LeetCode 2407. 最长递增子序列 II (Ts版)
最长递增子序列 II https://leetcode.cn/problems/longest-increasing-subsequence-ii/description/ 描述 给你一个整数数组 nums 和一个整数 k找到 nums 中满足以下要求的最长子序列: 子序列 严格递增子序列中相邻元素的差值 不超过 k请你返回满足上述要求的 最…...
电子电气架构 --- 什么是自动驾驶技术中的域控制单元(DCU)?
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…...
html5css3
1.html5新增语义化标签 <header><nav><article><section><aside><footer> 2.新增多媒体标签 视频<video>格式:map4,webm,ogg <video controls"controls" autoplay"autoplay" muted"mute…...
FPGA多路红外相机视频拼接输出,提供2套工程源码和技术支持
目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我这里已有的红外相机图像处理解决方案本博已有的已有的FPGA视频拼接叠加融合方案 3、工程详细设计方案工程设计原理框图红外相机FDMA多路视频拼接算法FDMA图像缓存视…...
python实战(十二)——如何进行新词发现?
一、概念 新词发现是NLP的一个重要任务,旨在从大量的文本数据中自动识别和提取出未在词典中出现的新词或短语,这对于信息检索、文本挖掘、机器翻译等应用具有重要意义,因为新词往往包含了最新的知识和信息。 随着互联网的不断发展,…...
动手做计算机网络仿真实验入门学习
打开软件 work1 添加串行接口模块,先关电源,添加之后再开电源 自动选择连接 所有传输介质 自动连接 串行线 绿色是通的,红色是不通的。 显示接口。se是serial串行的简写。 Fa是fast ethernet的简写。 为计算机配置ip地址: 为服…...
完整的 FFmpeg 命令使用教程
FFmpeg 是一个开源的跨平台音视频处理工具,它能够处理几乎所有的视频、音频格式,并提供了强大的功能如格式转换、视频剪辑、合并、提取音频等。FFmpeg 通过命令行界面(CLI)操作,尽管有一些图形界面的前端工具ÿ…...
Leetcode 3405. Count the Number of Arrays with K Matching Adjacent Elements
Leetcode 3405. Count the Number of Arrays with K Matching Adjacent Elements 1. 解题思路2. 代码实现 题目链接:3405. Count the Number of Arrays with K Matching Adjacent Elements 1. 解题思路 这一题虽然是一道hard的题目,但是委实是有点名不…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
