session-storage

本文探讨了前端页面如何与后端交互,重点介绍了local存储和session的区别,并提供了SessionStorage对象的get、set、remove和clearAll方法示例,强调了登录信息存储在SESSION_KEY_LOGIN_MEMBER中的应用场景。

前端页面与后端交互使用,注意local和session的区别

SESSION_KEY_LOGIN_MEMBER = "SESSION_KEY_LOGIN_MEMBER"; // 登录信息

SessionStorage = {
    get: function (key) {
        let v = sessionStorage.getItem(key);
        if (v && typeof(v) !== "undefined" && v !== "undefined") {
            return JSON.parse(v);
        }
    },
    set: function (key, data) {
        sessionStorage.setItem(key, JSON.stringify(data));
    },
    remove: function (key) {
        sessionStorage.removeItem(key);
    },
    clearAll: function () {
        sessionStorage.clear();
    }
};

bool tpsocket_event_storage_stream_to_cloud(struct tpsocket_handler *handler, struct list_head *buf, int event) { //debug_show_tpbuf_list(buf, "TEST", 3); struct tpsocket_fd *sock = container_of(handler, struct tpsocket_fd, handler); STORAGE_SESSION *storage_session = handler->priv; int err_code = 0; if (event != TPSOCKET_EVENT_WRITABLE) { MYDEBUG("storage stream to cloud event = %s, sock = %p, session = %p\n", tpsocket_event_name(event), sock, storage_session); if (storage_session) { DBG_DBG("Device Id = %s, session sock = %p\n", storage_session->dev_id, storage_session->sock); } } switch(event) { case TPSOCKET_EVENT_LISTEN: break; case TPSOCKET_EVENT_SHUTDOWN: break; case TPSOCKET_EVENT_ACCEPT: break; case TPSOCKET_EVENT_CONNECTED: MYDEBUG("STORAGESTREAM2CLOUD: %s:%s Connected\n", sock->addr, sock->port); if (false == storage_stream_consumer_post(storage_session)) return false; if (false == storage_start_read(storage_session)) { DBG_ERR("read stream file failed\n"); return false; } break; case TPSOCKET_EVENT_REQ_HEAD: break; case TPSOCKET_EVENT_RSP_HEAD: break; case TPSOCKET_EVENT_SUB_HEAD: break; case TPSOCKET_EVENT_UPGRADE: break; case TPSOCKET_EVENT_WRITABLE: if (storage_session->file && !list_empty(&(storage_session->file->parser.buf))) { if (storage_session->chunked && !tpsocket_chunk_encode(&(storage_session->file->parser.buf))) { tpsocket_free_buf(&(storage_session->file->parser.buf), tpsocket_event_name(event), 0); break; } storage_session_write_list_force(storage_session, &(storage_session->file->parser.buf), true); storage_session->file->read_buf_length = 0; } break; case TPSOCKET_EVENT_STREAM: return true; case TPSOCKET_EVENT_MESSAGE: err_code = common_check_error_code(buf); if (!err_code) { DBG_DBG("storage stream push success\n"); storage_session->post_success = 1; #ifndef TAPO_CAMERA } else if (err_code == -98400) { //If the recording/relay server finds out that the device is not eligible for cloud storage, // it returns an error code of -98400 upon which the firmware updates the cloud storage feature of that device. DEV_INFO *dev_info = get_dev_info(storage_session->storage_server->worker_ctx->top_ctx, storage_session->dev_id, NULL); if (dev_info) { dev_info->cloud_storage = false; } // mark as success here to avoid retrying. storage_session->post_success = 1; #endif } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); common_tpsocket_close_immediately(sock); break; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_KEEPALIVE: common_tpsocket_close_immediately(sock); break; case TPSOCKET_EVENT_CLOSED: if (storage_session) { tpsocket_unbind(sock, &storage_session->sock); uloop_timeout_cancel(&storage_session->reupload_tmo); tpsocket_free2(&storage_session->file, storage_session); if (storage_session->post_success) { storage_session->stream_send_to_cloud_flag = 0; } storage_session->uploading_flag = 0; storage_session_set_push_status(storage_session, 0); /* handle timeout immediately */ storage_server_timeout_handle_immediately(storage_session->storage_server); } break; case TPSOCKET_EVENT_ERROR: default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); return true; }bool storage_stream_upload(STORAGE_SESSION *storage_session) { DEV_INFO *dev_info = NULL; STORAGE_SERVER *storage_server; if (!storage_session) { DBG_ERR("arg NULL\n"); return false; } if (storage_session->sock) { DBG_DBG("sock exist\n"); return true; } storage_server = storage_session->storage_server; uloop_timeout_set(&storage_session->reupload_tmo, storage_session->reupload_idle_time); dev_info = get_dev_info(storage_server->worker_ctx->top_ctx, storage_session->dev_id, NULL); if (!dev_info) { DBG_ERR("Not find device\n"); return false; } /* create socket */ struct tpsocket_handler storage_stream_to_cloud = { .cb = tpsocket_event_storage_stream_to_cloud, .cer = MEDIACENTER_CERTFILE, .write_buf_max = STORAGE_MEMORY_CACHE_LIMIT, }; storage_session->retry_count++; if ((storage_session->sock = tpsocket_from_url(dev_info->relay_storage_url, &storage_stream_to_cloud))) { //if (storage_session->sock = tpsocket_from_url("http://192.168.137.103:8010", &storage_stream_to_cloud)) { DBG_DBG("Create session sock = %p, session = %p\n", storage_session->sock, storage_session); storage_session->sock->handler.priv = storage_session; storage_session->uploading_flag = 1; storage_session_set_push_status(storage_session, 1); } return true; } bool storage_start_read(STORAGE_SESSION *storage_session) { if (!storage_session) { DBG_ERR("arg NULL\n"); return false; } struct tpsocket_handler client = { .cb = storage_read_file, .flowcontrol = 10*1024, .priv = storage_session, .read_buf_max = STORAGE_MEMORY_CACHE_LIMIT, }; if (STORAGE_STREAMING == storage_session->storage_type) { storage_session->file = tpsocket_new(NULL, "stream", NULL, storage_session->stream_path, TPSOCKET_TYPE_FILE, &client); if (!storage_session->file) { DBG_ERR("open %s failed\n", storage_session->stream_path); return false; } } else { storage_session->file = tpsocket_new(NULL, "read", NULL, storage_session->snapshot_path, TPSOCKET_TYPE_FILE, &client); if (!storage_session->file) { DBG_ERR("open %s failed\n", storage_session->snapshot_path); return false; } } DBG_DBG("session = %p, sock = %p, open file = %p\n", storage_session, storage_session->sock, storage_session->file); return true; }bool storage_read_file(struct tpsocket_handler*handler, struct list_head*buf, int event) { STORAGE_SESSION *storage_session = handler->priv; //MYDEBUG("storage read file event = %s, sock = %p, consumer = %p\n", tpsocket_event_name(event), sock, storage_session); switch(event) { case TPSOCKET_EVENT_CONNECTED: break; case TPSOCKET_EVENT_REQ_HEAD: break; case TPSOCKET_EVENT_RSP_HEAD: break; case TPSOCKET_EVENT_UPGRADE: break; case TPSOCKET_EVENT_SUB_HEAD: case TPSOCKET_EVENT_STREAM: case TPSOCKET_EVENT_MESSAGE: if (false == storage_file_produce(storage_session, buf)) { return false; } goto out; //break; case TPSOCKET_EVENT_RESET: break; case TPSOCKET_EVENT_CLOSED: if (storage_session) { storage_session->file = NULL; if (storage_session->sock) { if (!list_empty(buf)) { if (storage_session->chunked) { tpsocket_chunk_encode(buf); tpsocket_write_list_force(storage_session->sock, buf, true); } } if (STORAGE_STREAMING == storage_session->storage_type) { storage_session_stream_add_tail(storage_session); } else { storage_session_snapshot_add_tail(storage_session); } } } break; case TPSOCKET_EVENT_ERROR: default: break; } tpsocket_free_buf(buf, tpsocket_event_name(event), 0); out: return true; }bool storage_file_produce(STORAGE_SESSION *storage_session, struct list_head *buf) { if (!storage_session) { DBG_ERR("arg NULL\n"); return false; } if (!storage_session->sock) { DBG_ERR("%p arg NULL, file = %p\n", storage_session, storage_session->file); return false; } if (tpsocket_writable(storage_session->sock)) { if (!list_empty(buf) && storage_session->chunked && !tpsocket_chunk_encode(buf)) { tpsocket_free_buf(buf, "PRODUCE", 0); return false; } storage_session_write_list_force(storage_session, buf, true); } return true; }typedef struct _STORAGE_SESSION_ { struct list_head list; struct list_head headers; struct tpsocket_fd *sock; struct tpsocket_fd *file; int store; int chunked; int ts_encoded; int stream; bool storage_success; char dev_id[LEN_MAX_ID]; char dev_ip[LEN_MAX_ID]; char host[LEN_MAX_HOST]; char cookie[LEN_MAX_COOKIE]; char xtoken[LEN_MAX_TOKEN]; char event_id[LEN_MAX_EVENT_ID]; time_t event_timestamp; enum EVENT_TYPE event_type; int count_id; int region_buf_len; char region_buf[LEN_MAX_128*4]; int storage_type; int content_len; char snapshot_path[LEN_MAX_PATH]; char stream_path[LEN_MAX_PATH]; bool stream_send_to_cloud_flag; bool snapshot_send_to_cloud_flag; bool uploading_flag; bool delete_flag; int retry_count; int post_success; // unsigned long long reupload_total_load; unsigned long long reupload_last_load; unsigned long long reupload_last_sent; int reupload_idle_time; struct uloop_timeout reupload_tmo; void *producer; void *iot_consumer; STORAGE_SERVER *storage_server; } STORAGE_SESSION; 参考这个代码重新帮我实现日志的读写功能。
10-20
<think>我们参考提供的storage_stream_upload等函数,重新实现日志读写功能。主要思路: 1. 使用类似STORAGE_SESSION的结构来管理日志传输会话 2. 分离文件读取和网络写入,通过事件驱动 3. 使用分块传输避免阻塞 实现步骤: - 创建日志会话结构体(类似STORAGE_SESSION- 实现文件读取回调(类似storage_read_file) - 实现网络传输回调(类似tpsocket_event_storage_stream_to_cloud) - 实现上传启动函数(类似storage_stream_upload) 具体代码实现如下: </think>### 日志读写功能重构方案 #### 核心设计要点 1. **会话状态管理**: ```c typedef struct { FILE* fp; // 日志文件指针 size_t file_size; // 文件总大小 size_t sent_bytes; // 已发送字节数 bool header_sent; // HTTP头发送标志 char filepath[256]; // 文件路径 struct tpsocket_fd* sock; // 关联的socket struct uloop_timeout tmo; // 超时控制器 } LogSession; ``` 2. **事件驱动架构**: ```c // 主事件处理函数 bool log_event_handler(struct tpsocket_handler *handler, struct list_head *buf, int event) { LogSession *session = handler->priv; switch(event) { case TPSOCKET_EVENT_CONNECTED: log_init_transfer(session); break; case TPSOCKET_EVENT_WRITABLE: log_send_data(session); break; case TPSOCKET_EVENT_CLOSED: log_cleanup(session); break; // 其他事件处理... } return true; } ``` #### 关键功能实现 ##### 1. 日志传输初始化 ```c bool log_init_transfer(LogSession *session) { // 发送HTTP头 char header[512]; snprintf(header, sizeof(header), "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: %zu\r\n" "Connection: close\r\n\r\n", session->file_size); struct tpsocket_buf *header_buf = tpbuf_snprintf(strlen(header)+1, header); if (!tpsocket_write(session->sock, header_buf)) { DBG_ERR("Header send failed"); return false; } session->header_sent = true; return true; } ``` ##### 2. 分块数据传输 ```c bool log_send_data(LogSession *session) { #define CHUNK_SIZE 65536 uint8_t buffer[CHUNK_SIZE]; // 检查可写空间 if (tpsocket_writable(session->sock) < CHUNK_SIZE/2) return true; // 读取文件块 size_t bytes_read = fread(buffer, 1, CHUNK_SIZE, session->fp); if (bytes_read <= 0) { if (feof(session->fp)) { session->transfer_complete = true; tpsocket_close(session->sock); // 优雅关闭 } return true; } // 发送数据 struct tpsocket_buf *data_buf = tpbuf_new(bytes_read); memcpy(data_buf->data, buffer, bytes_read); if (!tpsocket_write(session->sock, data_buf)) { DBG_ERR("Data write failed"); tpbuf_free(data_buf); return false; } // 更新状态 session->sent_bytes += bytes_read; // 进度追踪 if (session->sent_bytes % (1024*1024) == 0) { DBG_INFO("Sent: %.1f%% (%zu/%zu)", (double)session->sent_bytes/session->file_size*100, session->sent_bytes, session->file_size); } return true; } ``` ##### 3. 资源清理 ```c void log_cleanup(LogSession *session) { if (session->fp) { fclose(session->fp); session->fp = NULL; } if (session->sock) { tpsocket_unbind(session->sock); session->sock = NULL; } free(session); } ``` #### 4. 会话管理 ```c bool start_log_transfer(const char *filepath, struct tpsocket_fd *sock) { // 打开日志文件 FILE *fp = fopen(filepath, "rb"); if (!fp) { DBG_ERR("File open failed: %s", filepath); return false; } // 获取文件大小 struct stat st; fstat(fileno(fp), &st); // 创建会话 LogSession *session = calloc(1, sizeof(LogSession)); session->fp = fp; session->file_size = st.st_size; session->sock = sock; strncpy(session->filepath, filepath, sizeof(session->filepath)); // 设置超时控制器 session->tmo.cb = log_timeout_handler; uloop_timeout_set(&session->tmo, 30000); // 30秒超时 // 绑定事件处理器 struct tpsocket_handler handler = { .cb = log_event_handler, .priv = session, .write_buf_max = 1024*1024 // 1MB写缓冲区 }; tpsocket_bind(sock, &handler); return true; } ``` #### 5. 超时处理 ```c void log_timeout_handler(struct uloop_timeout *tmo) { LogSession *session = container_of(tmo, LogSession, tmo); DBG_ERR("Log transfer timeout: %s", session->filepath); tpsocket_close(session->sock); } ``` ### 优化特性 1. **流量控制**: - 通过 `tpsocket_writable()` 动态检测可用缓冲区 - 自动暂停传输当缓冲区不足 2. **错误恢复**: ```c if (!log_send_data(session)) { uloop_timeout_set(&session->tmo, 1000); // 1秒后重试 } ``` 3. **内存安全**: - 使用 `calloc` 确保会话结构体零初始化 - 严格检查指针有效性 - 文件描述符双重关闭防护
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值