Browse Source

fix: ftp,解决air8101下,task任务先运行,导致netc还没就绪的问题

Wendal Chen 2 months ago
parent
commit
482db8c2f6
2 changed files with 105 additions and 16 deletions
  1. 56 11
      components/network/libftp/luat_ftp_client.c
  2. 49 5
      olddemo/ftp/main.lua

+ 56 - 11
components/network/libftp/luat_ftp_client.c

@@ -317,8 +317,9 @@ static int luat_ftp_pasv_connect(luat_ftp_ctrl_t *ftp_ctrl,uint32_t timeout_ms){
 static int ftp_login(void)
 {
 	int ret;
-	if(network_connect(g_s_ftp.network->cmd_netc, g_s_ftp.network->addr, strlen(g_s_ftp.network->addr), NULL, g_s_ftp.network->port, FTP_SOCKET_TIMEOUT)){
-		LLOGE("ftp network_connect fail");
+	ret = network_connect(g_s_ftp.network->cmd_netc, g_s_ftp.network->addr, strlen(g_s_ftp.network->addr), NULL, g_s_ftp.network->port, FTP_SOCKET_TIMEOUT);
+	if (ret) {
+		LLOGE("ftp network_connect fail %d", ret);
 		return -1;
 	}
 	ret = luat_ftp_cmd_recv(&g_s_ftp,g_s_ftp.network->cmd_recv_data,&g_s_ftp.network->cmd_recv_len,FTP_SOCKET_TIMEOUT);
@@ -450,6 +451,7 @@ static void ftp_task(void *param){
 	OS_EVENT task_event;
 	uint8_t is_timeout = 0;
 
+	luat_rtos_task_sleep(10); // 起来就等10ms, 给调用者一点时间运行完毕
 
 	g_s_ftp.is_run = 1;
 	luat_rtos_event_recv(g_s_ftp.task_handle, FTP_EVENT_LOGIN, &task_event, NULL, LUAT_WAIT_FOREVER);
@@ -691,6 +693,7 @@ wait_event_and_out:
 
 
 int luat_ftp_login(uint8_t adapter,const char * ip_addr,uint16_t port,const char * username,const char * password,luat_ftp_tls_t* luat_ftp_tls,luat_ftp_cb_t ftp_cb){
+	int result = 0;
 	if (g_s_ftp.network){
 		LLOGE("ftp already login, please close first");
 		return FTP_ERROR_STATE;
@@ -709,23 +712,47 @@ int luat_ftp_login(uint8_t adapter,const char * ip_addr,uint16_t port,const char
 		LLOGE("bad network adapter index %d", g_s_ftp.network->adapter_index);
 		return FTP_ERROR_STATE;
 	}
+	LLOGD("ftp adapter %d host %s port %d", g_s_ftp.network->adapter_index, ip_addr, port);
 	g_s_ftp.network->cmd_netc = network_alloc_ctrl(g_s_ftp.network->adapter_index);
 	if (!g_s_ftp.network->cmd_netc){
 		LLOGE("cmd_netc create fail");
 		return FTP_ERROR_NO_MEM;
 	}
 	g_s_ftp.network->port = port;
-	if (strlen(ip_addr) > 0 && strlen(ip_addr) < 64)
+
+	if (strlen(ip_addr) > 0 && strlen(ip_addr) < 64) {
 		memcpy(g_s_ftp.network->addr, ip_addr, strlen(ip_addr) + 1);
-	if (strlen(username) > 0 && strlen(username) < 64)
+	}
+	else {
+		LLOGE("invalid ip address length %d", strlen(ip_addr));
+		result = -20;
+		goto error;
+	}
+	if (strlen(username) > 0 && strlen(username) < 64) {
 		memcpy(g_s_ftp.network->username, username, strlen(username) + 1);
-	if (strlen(password) > 0 && strlen(password) < 64)
+	}
+	else {
+		LLOGE("invalid username length %d", strlen(username));
+		result = -21;
+		goto error;
+	}
+	if (strlen(password) > 0 && strlen(password) < 64) {
 		memcpy(g_s_ftp.network->password, password, strlen(password) + 1);
+	}
+	else {
+		LLOGE("invalid password length %d", strlen(password));
+		result = -22;
+		goto error;
+	}
+
 	if (luat_ftp_tls == NULL){
 		network_deinit_tls(g_s_ftp.network->cmd_netc);
-	}else{
+	}
+	else {
 		if (network_init_tls(g_s_ftp.network->cmd_netc, (luat_ftp_tls->server_cert || luat_ftp_tls->client_cert)?2:0)){
-			return FTP_ERROR_CLOSE;
+			LLOGE("ftp tls init fail");
+			result = -23;
+			goto error;
 		}
 		if (luat_ftp_tls->server_cert){
 			network_set_server_cert(g_s_ftp.network->cmd_netc, (const unsigned char *)luat_ftp_tls->server_cert, strlen(luat_ftp_tls->server_cert)+1);
@@ -736,17 +763,30 @@ int luat_ftp_login(uint8_t adapter,const char * ip_addr,uint16_t port,const char
 					(const unsigned char *)luat_ftp_tls->client_password, strlen(luat_ftp_tls->client_password)+1);
 		}
 	}
-	network_set_ip_invaild(&g_s_ftp.network->ip_addr);
-	int result = luat_rtos_task_create(&g_s_ftp.task_handle, 8*1024, 10, "ftp", ftp_task, NULL, 16);
+
+	// task会主动等10ms
+	result = luat_rtos_task_create(&g_s_ftp.task_handle, 8*1024, 10, "ftp", ftp_task, NULL, 16);
 	if (result) {
 		LLOGE("创建ftp task失败!! %d", result);
-		return result;
+		goto error;
 	}
+	
+	network_set_ip_invaild(&g_s_ftp.network->ip_addr);
 	network_init_ctrl(g_s_ftp.network->cmd_netc,g_s_ftp.task_handle, ftp_task_cb, NULL);
 	network_set_base_mode(g_s_ftp.network->cmd_netc, 1, 30000, 0, 0, 0, 0);
 	network_set_local_port(g_s_ftp.network->cmd_netc, 0);
+	// g_s_ftp.network->cmd_netc->is_debug = 1;
+
 	luat_rtos_event_send(g_s_ftp.task_handle, FTP_EVENT_LOGIN, 0, 0, 0, LUAT_WAIT_FOREVER);
 	return 0;
+error:
+	// 清理资源
+	if (g_s_ftp.network->cmd_netc) {
+		network_force_close_socket(g_s_ftp.network->cmd_netc);
+		network_release_ctrl(g_s_ftp.network->cmd_netc);
+		g_s_ftp.network->cmd_netc = NULL;
+	}
+	return result;
 }
 
 int luat_ftp_command(const char * command){
@@ -838,4 +878,9 @@ int luat_ftp_push(const char * local_name,const char * remote_name){
 	return 0;
 }
 
-void luat_ftp_debug(uint8_t on_off) {g_s_ftp.debug_onoff = on_off;}
+void luat_ftp_debug(uint8_t on_off) {
+	g_s_ftp.debug_onoff = on_off;
+	if (NULL != g_s_ftp.network && g_s_ftp.network->cmd_netc) {
+		g_s_ftp.network->cmd_netc->is_debug = on_off;
+	}
+}

+ 49 - 5
olddemo/ftp/main.lua

@@ -17,7 +17,7 @@ local server_port = 21 -- 服务器端口号
 local server_username = "ftp_user" -- 服务器登陆用户名
 local server_password = "3QujbiMG" -- 服务器登陆密码
 
-local is_ssl = flase -- 非ssl加密连接
+local is_ssl = false -- 非ssl加密连接
 -- local is_ssl =true --如果是不带证书的加密打开这句话
 
 -- local ssl_encrypt = {
@@ -31,7 +31,7 @@ local is_ssl = flase -- 非ssl加密连接
 
 -- 这里使用模块唯一ID来生成文件名,避免多个模块使用同一ftp服务器时文件名冲突
 local self_id = mcu.unique_id():toHex()
-local local_name = "/" .. self_id .. ".txt" -- 模块内部文件名及其路径
+local local_name = "/ram/" .. self_id .. ".txt" -- 模块内部文件名及其路径
 local remote_name = "/" .. self_id .. "_srv.txt" -- 服务器上的文件名及其路径
 
 sys.taskInit(function()
@@ -66,6 +66,7 @@ local function ftp_test()
     sys.waitUntil("net_ready") -- 死等到联网成功
     local result = false
     local adapter = nil -- 自动选择网络适配器
+    ftp.debug(true) -- 打开调试开关, 可以看到和服务器交互的明文命令和返回值
     while true do
         sys.wait(1000)
         log.info("ftp 启动")
@@ -94,28 +95,71 @@ local function ftp_test()
         -- 演示获取当前工作目录下的文件列表, 非必须的操作
         log.info("获取当前工作目录下的文件名列表", ftp.command("LIST").wait())
         
-        -- 生成一段随机数据, 确保每次是新数据, 保证测试的可用性
-        local test_data = crypto.trng(128)
+        -- 生成至少51KB的测试数据 (52KB = 53248字节)
+        local target_size = 52*1024
+        local test_data = ""
+        
+        -- 使用循环生成足够大的数据
+        log.info("开始生成测试数据,目标大小:", target_size, "字节")
+        while #test_data < target_size do
+            -- 每次生成1KB的随机数据,直到达到目标大小
+            local chunk_size = math.min(1024, target_size - #test_data)
+            local chunk = crypto.trng(chunk_size)
+            test_data = test_data .. chunk
+            -- log.info("已生成数据:", #test_data, "/", target_size, "字节")
+        end
+        
+        log.info("测试数据生成完成,总大小:", #test_data, "字节")
+        
         -- 把数据写到本地目录
         log.info("在本地创建一个文件", "文件名及其目录为" .. local_name)
         io.writeFile(local_name, test_data)
+        log.info("本地文件大小", #test_data, "字节")
+        log.info("本地文件大小(KB)", #test_data / 1024, "KB")
         
         -- 把文件上传到服务器去
         log.info("上传本地的" .. local_name, "到服务器上并且更名为" .. remote_name)
         result = ftp.push(local_name, remote_name).wait()
         log.info("上传结果是", result)
 
+        -- 打印一下服务器当前目录下的文件列表
+        log.info("获取当前工作目录下的文件名列表", ftp.command("LIST").wait())
+
         -- 从服务器上下载刚才上传的文件
         log.info("下载服务器上的" .. remote_name, "存放在" .. remote_name)
         result = ftp.pull(remote_name, remote_name).wait()
         log.info("下载结果是", result)
 
+        -- 检查下载的文件大小
+        local downloaded_data = io.readFile(remote_name)
+        if downloaded_data then
+            log.info("下载文件实际大小", #downloaded_data, "字节")
+            log.info("下载文件实际大小(KB)", #downloaded_data / 1024, "KB")
+            log.info("期望文件大小", #test_data, "字节")
+            log.info("期望文件大小(KB)", #test_data / 1024, "KB")
+            
+            if #downloaded_data ~= #test_data then
+                log.warn("警告:下载文件大小与期望大小不一致!")
+                log.warn("期望大小:", #test_data, "字节 (", #test_data / 1024, "KB)")
+                log.warn("实际大小:", #downloaded_data, "字节 (", #downloaded_data / 1024, "KB)")
+                log.warn("大小差异:", #test_data - #downloaded_data, "字节")
+            end
+        else
+            log.error("无法读取下载的文件")
+        end
+
         -- 比较一下上传和下载的数据是否一致
         local downloaded_data = io.readFile(remote_name)
-        if downloaded_data == test_data then
+        if downloaded_data and downloaded_data == test_data then
             log.info("上传和下载的数据一致性验证通过")
         else
             log.error("上传和下载的数据一致性验证失败")
+            if downloaded_data then
+                log.info("原始数据长度:", #test_data, "字节 (", #test_data / 1024, "KB)")
+                log.info("下载数据长度:", #downloaded_data, "字节 (", #downloaded_data / 1024, "KB)")
+            else
+                log.error("无法读取下载的数据")
+            end
         end
 
         -- 删除服务器上的测试文件