接收多播数据时,我将收到的数据(u_char *)发给消息响应函数来处理,结果数据居然丢了,只剩4个字节,为什么呢?

在接收多播数据时,使用u_char *类型发送给消息处理函数处理,但发现数据仅保留4个字节。问题可能出在数据传递过程中。检查了内存分配和消息传递,但数据长度始终为4,可能的原因包括数据类型转换错误或缓冲区大小不匹配。进一步分析代码以定位问题所在。
 接收多播数据时,我将收到的数据(u_char *)发给消息响应函数来处理,结果数据居然丢了,只剩4个字节,为什么呢?

// 接收多播消息线程
DWORD WINAPI CTestDlg::RecvMCProc(LPVOID lpParameter)
{
    SOCKET sock;
    HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;
    CString sWSIP = "192.168.1.10";

    delete lpParameter;    //别忘了释放内存
    
    WSADATA wsd;
    struct sockaddr_in local,remote;
    SOCKET sockM;

    int len = sizeof( struct sockaddr_in);
    //初始化WinSock2.2
    if( WSAStartup( MAKEWORD(2,2),&wsd) != 0 )
    {
        AfxMessageBox("函数 WSAStartup() 初始化WinSock2.2 失败/n");
        return false;
    }
    if((sock=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,
        WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF|
        WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
    {
        AfxMessageBox("WSASocket 创建socket失败:%d/n",WSAGetLastError());
        WSACleanup();
        return false;
    }
    //将sock绑定到本机用于FA3数据交换的多播端口上。
    local.sin_family = AF_INET;
    local.sin_port = htons(MCASTPORT);
    local.sin_addr.S_un.S_addr=inet_addr(sWSIP);
    
    if( bind(sock ,(struct sockaddr*)&local,sizeof(local)) == SOCKET_ERROR )
    {
        AfxMessageBox( "绑定到本机的多播端口失败:%d /n",WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return false;
    }
    //加入多播组
    remote.sin_family = AF_INET;
    remote.sin_port = htons(MCASTPORT);
    remote.sin_addr.s_addr = inet_addr( MCASTADDR );
    /* Winsock2.0*/
    if(( sockM = WSAJoinLeaf(sock,(SOCKADDR*)&remote,sizeof(remote),NULL,NULL,NULL,NULL, JL_BOTH)) == INVALID_SOCKET)
    {
        AfxMessageBox("加入多播组失败,WSAJoinLeaf() failed:%d/n",WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        return false;
    }
    
    SOCKADDR_IN addrFrom;
    
    u_char recvBuf[BUFSIZE];
    int retval;
    while(TRUE)
    {
        retval=recvfrom(sock,(char *)recvBuf,BUFSIZE,0,(SOCKADDR*)&addrFrom,&len);
        if(SOCKET_ERROR==retval)
            break;
// 这里 retval=304 ,总之比较多,是个结构体,含有很多个字符串等
             //将消息内容和IP传给窗体的消息处理函数
            ::PostMessage(hwnd,WM_RECVMCDATA,0,(LPARAM)recvBuf);
        }
    }
    return 0;
}

// MultiCast消息处理函数
void CTestDlg::OnRecvMCData(WPARAM wParam,LPARAM lParam)
{
    u_char *MCData;
    MCData= (u_char *) malloc(BUFSIZE);
    MCData=(u_char *)lParam;  // 地址是对的,就是数据被截断了,后面的没有了!只有4个字节!
    int iDataLength=sizeof(MCData); // ==4???????
    
    // 下面打印出来看看,这段有点乱,就是想看看数据
    CString sTmpByte,sData;
    for (int i=1; i < iDataLength ; i++)
    {
        sTmpByte.Format("%.2x ", MCData[i-1]);
        sData+=sTmpByte;
        if ( (i % 16) == 0) sData+="/r/n";
         }
    // 在文本框内显示接收到的消息,新收到的在最上一行
    CString str,sTmp;
    GetDlgItemText(IDC_MCText,sTmp);
    str+=sData+"/r/n";
    str+=sTmp;
    SetDlgItemText(IDC_MCText,str);
}
/****************************************************************************** * Copyright (c) 2018-2018 TP-Link Systems Inc. * * Filename: httpd.h * Version: 1.0 * Description: http 服务模块头文件 * Author: liyijie<liyijie@tp-link.com.cn> * Date: 2018-9-10 ******************************************************************************/ #ifndef __HTTPD_H__ #define __HTTPD_H__ #include <sys/stat.h> #include <netinet/in.h> #include "http_common.h" #include "json/json.h" /* for JSON_OBJPTR */ #include "sslApi.h" #define HTTPD_DEBUG(fmt, ...) NSD_DEBUG(NSD_HTTPD, "[HTTPD]" fmt, ##__VA_ARGS__) #define HTTPD_WARNING(fmt, ...) NSD_WARN(NSD_HTTPD, "[HTTPD]" fmt , ##__VA_ARGS__) #define HTTPD_ERROR(fmt, ...) NSD_ERROR(NSD_HTTPD, "[HTTPD]" fmt , ##__VA_ARGS__) #define HTTPD_ERROR_LOG(fmt, ...) NSD_LOG(LOG_ERROR, LOG_CONNECTIVITY, "[HTTPD]" fmt, ##__VA_ARGS__) #define HTTPD_INFO_LOG(fmt, ...) NSD_LOG(LOG_INFO, LOG_CONNECTIVITY, "[HTTPD]" fmt, ##__VA_ARGS__) #define HTTP_MAX_CONTEXT 20 #define HTTP_MAX_ACCEPT 20 #define HTTP_CONTEXT_TIMEOUT 10 #define HTTP_IO_TIMEOUT 3 #define HTTP_URL_SIZE 80 #define HTTP_RECV_CONTENT_TIMEOUT 90 #define HTTP_SECTOR_SIZE 4 * 1024 #define HTTP_HEAD_BUF_SIZE 4 * 1024 #define HTTP_HEADER_SIZE 2 * 1024 #define HTTP_UPNP_HEADER_SIZE 1 * 1024 /* upnp的http头部大小 */ #define HTTP_SESSION_TIMEOUT 1800 /* 约半个小 */ #define HTTP_KEY_INTERVAL 120 /* 每隔两分钟更换一次session。 */ #define HTTP_MAX_SESSION 20 #define HTTP_SESSION_SIZE 36 #define HTTP_SESSION_STOK_SIZE 32 #define HTTP_SESSION_LOCK_MAX 10 #define HTTP_MAX_DICTIONARY_LEN 221 #define HTTP_ETAG_SIZE 32 #define HTTP_TIME_SIZE 64 #define HTTPD_DEFAULT_INDEX "/www/admin/Index.htm" #define HTTP_USER_GROUP_NAME_LEN 16 typedef enum _HTTP_GROUP_TYPE { GROUP_HTTPD = 0, GROUP_HTTPSD, GROUP_UPNP, GROUP_ONVIF, #ifdef OPENAPI_SUPPORT GROUP_OPENAPI, #endif GROUP_MAX }HTTP_GROUP_TYPE; typedef struct _HTTP_SESSION { BOOL idle; U32 client; /* 认证客户端。 */ U32 timeout; /* SESSION的老化间,正常情况下10分钟,登录错误次数超过20次则被永久锁定。 */ char key[HTTP_SESSION_SIZE]; /* 认证密钥,每次认证之前动态生成,发给客户端。 */ char tmp_key[HTTP_SESSION_SIZE]; /* 临认证密钥,首次认证之前动态生成。 */ char dictionary[HTTP_MAX_DICTIONARY_LEN + 1]; /* 密钥字典 */ U32 key_interval; /* 密钥更换间间隔。 */ BOOL be_clt_alive; /* 标识客户端是否活跃 */ U32 auth_group; /* 次级用户组:USER_ROOT, USER_ADMIN, USER_GUEST, USER_HUB */ U32 auth_index; /* 保存所在用户组的位置,标识同一用户组的不同用户 */ #ifdef LOCAL_PROTOCOL_SECURE int last_seq; /* 防重放:当前本地维护的序列号 */ int req_now_seq; /* 防重放:当前报文中的序列号 */ int need_update_last_seq; /* 防重放:30s到了的标志 */ int g_parse_seq_timer; /* 防重放:定接收值 */ #endif }HTTP_SESSION; #ifdef LOCAL_PROTOCOL_SECURE typedef struct _ENCRYPT_ARRAY { BOOL idle; U32 client; char cnonce[ENCRYPT_NONCE_LEN + 1]; char nonce[ENCRYPT_NONCE_LEN + 1]; char device_confirm[DEVICE_CONFIRM_LEN + 1]; /* 用于登录认证的校验字段 */ char app_confirm[DEVICE_CONFIRM_LEN + 1]; char pre_tapo_tag[SHA256_BLOCK_SIZE + 1]; /* 计算app_confirm先计算tapo_tag的一部分,避免重复计算 */ char tapo_tag[SHA256_BLOCK_SIZE + 1]; /* 防篡改:报文头部的tag */ unsigned char aes_key[AES128_KEY_BYTES + 1]; /* 用于AES加密的密钥 */ unsigned char aes_iv[AES128_IV_BYTES + 1]; char passwd[SHA256_BLOCK_SIZE + 1]; /* 登录认证的密码 */ #ifdef HOMEKIT_ONBOARDING_SUPPORT U8 hk_info_login_flag; /* 使用homekit信息(setup code/setup payload)登录 */ #endif }ENCRYPT_ARRAY; #endif typedef struct _CONTEXT CONTEXT; typedef struct _HTTP_GROUP_SRV { S32 (*match_port)(U16 port); S32 (*match_auth)(CONTEXT *context); S32 (*data_srv)(CONTEXT *context); /* 数据处理阶段 */ S32 (*make_rsp)(CONTEXT *context); /* 数据响应阶段 */ #if defined(INCLUDE_UPNP_SERVER) S32 (*make_rsp_extend)(CONTEXT *context); /* 数据响应发送前的最后处理 */ #endif } HTTP_GROUP_SRV; /* 数据socket所在的结构 */ typedef struct _CONTEXT { S32 sock; /* 当前连接的会话套接字 */ U16 port; U32 timeout; /* 本链接的老化间。 */ char *host; char *if_none_match; char *if_modified_since; S32 async_buffer_len; /* 未完成发送的静态页面文件剩余长度。 */ S32 recv_count; /* 确认是否需要异步接收 */ S32 code; HTTP_MEDIA_TYPE media_type; BOOL disposition; S32 regard; struct sockaddr_in client; S32 (*parser)(struct _CONTEXT *context); HTTP_GROUP_SRV *group_srv; /* 初级用户组:根据 port 区分 */ void *onvif_soap; char *head_buf; char *content_buf; char *head_end; char *head_buf_end; char *hbuf_data_end; char *content_start; char *content_end; char *content_buf_end; char *boundary; char *platform; char *refer; /* 有session验证,暂不需要refer检查。 */ #if defined(INCLUDE_UPNP_SERVER) char *soap; /* HTTP扩展头部,用于UPnP。 */ char *man; /* HTTP扩展头部,用于UPnP。 */ char *callback; /* HTTP扩展头部,用于UPnP。 */ S32 sid_timeout; /* HTTP扩展头部,用于UPnP,订阅老化间,0表示无限。 */ char *sid; #endif char path[HTTP_URL_SIZE]; HTTP_ARG arg_list[HTTP_ARGLIST_SIZE]; S32 header_len; S32 content_len; #ifdef MAKEROOM_BEFORE_UPGRADE U32 precheck_len; BOOL precheck_ok; BOOL is_upgrade; #endif S32 post_handle_code; BOOL rsp_file; char rsp_file_path[HTTP_URL_SIZE * 2]; struct stat rsp_file_stat; HTTP_METHOD method; /* HTTP方法,GET/POST。 */ HTTP_VERSION version; /* HTTP版本,1.0/1.1 */ BOOL keepalive; /*是否使用持续连接*/ BOOL chunked; /*是否使用chunk传输*/ BOOL origin; /*是否存在Origin*/ BOOL done; /* 指名数据有无收完。 */ BOOL json; /* 表示请求是否是JSON请求 */ BOOL soap_xml; /* 表示请求是否是soap+xml请求 */ BOOL remove_first_boundary; /* 表示是否移除了第一个boundary */ HTTP_SESSION *session; char *key; char etag[HTTP_ETAG_SIZE]; char last_modified[HTTP_TIME_SIZE]; char passwd[USER_MANAGEMENT_PASSWD_MAX_STR_LEN]; char stok[HTTP_SESSION_SIZE]; U32 idle; DS_HANDLE_CONTEXT ds_context; BOOL is_https; void *ssl_ctx; S32 is_ssl_setfd; /* 是否设置fd到ssl结构体 */ /* 此标志位暂为了升级用,升级后必须重启,否则在http_reset_context等处造成内存泄漏 */ BOOL keep_forever; BOOL is_ssl_success; S32 ssl_handshake_num; BOOL is_http_header_parser_done; BOOL is_reserve; /* 保留context内容标志位 */ #ifdef LOCAL_PROTOCOL_SECURE S32 seq; BOOL seq_verify_fail; /* 头部解析seq解析失败 */ #endif }CONTEXT; typedef struct _HTTP_METHOD_HANDLE { S32 (*handle)(struct _CONTEXT *context); S32 (*make_extent_header)(struct _CONTEXT *context); }HTTP_METHOD_HANDLE; //typedef struct _HTTP_GROUP //{ // struct _HTTP_GROUP_LIST // { // BOOL enable; // U32 client; // U8 home[64]; // U16 port; // }list[GROUP_MAX]; //}HTTP_GROUP; /** * 返回 group 的默认端口(HTTPD 的 80 端口) * * * Return value: port */ U16 get_group_default_port(void); #ifdef LOCAL_PROTOCOL_SECURE BOOL get_factory_mode_from_httpd(); #endif /** * 根据不同用户组获取监听端口; * * Out: 创建的TCP socket; * * Return value: N/A; */ S32 http_group_listen_port(S32 group, U16 listen_port, S32 *out_sock); /** * 增加组信息和数据处理函数; * * Return value: N/A; */ S32 http_group_srv_add(S32 group, void *match_port, void *match_auth, void *data_srv, void *make_rsp); #if defined(INCLUDE_UPNP_SERVER) S32 http_group_srv_add_rsp_extend(S32 group, void *make_rsp_extend); #endif HTTP_GROUP_SRV *http_get_group_srv_addr(S32 group); BOOL check_group(CONTEXT *context, HTTP_GROUP_TYPE group); #endif /* __HTTPD_H__ */
09-09
LOCAL S32 http_parse_header(CONTEXT *context) { char *pointer = NULL; char *line = NULL; char *value = NULL; /* 开始解析HTTP包头。 */ line = http_read_line(context); if (NULL == line) /* 读取失败 */ { if (1 == context->is_reserve) { return RESERVE; } HTTPD_ERROR("read line fail."); return ERROR; } /* 解析头部第一行,因为受行格式和其它行不一致,需要单独解析。 */ pointer = http_parse_method(context, line); if (NULL == pointer) { return ERROR; } /* 提取path、URL以及相关参数; */ pointer = http_parse_url(context, pointer); if (NULL == pointer) { return ERROR; } if (OK != http_parse_version(context, pointer)) { return ERROR; } /* HTTP包头其他行,遵循相同的格式:key:value\r\n */ line = http_read_line(context); if (1 == context->is_reserve) { return RESERVE; } while ((NULL != line) && ('\0' != *line)) { if ((' ' == *line) || ('\t' == *line)) { goto read_next_line; } /* 开始解析行,每一行必须是KEY:VALUE的格式,如果不是,则格式错误。 */ pointer = strchr(line, ':'); if (NULL == pointer) { goto read_next_line; } *pointer = '\0'; value = shift(pointer + 1); if (OK != http_parse_key(context, line, value)) { return ERROR; } read_next_line: line = http_read_line(context); if (1 == context->is_reserve) { return RESERVE; } } context->is_http_header_parser_done = 1; #ifdef FAC_MODEL_ENABLE if (context->keepalive) { if (NULL == context->platform || 0 != strcmp(context->platform, FACTORY_USER_AGENT)) { context->keepalive = FALSE; /* 非产测不用长连接 */ } } #endif return OK; }LOCAL char *http_read_line(CONTEXT *context) { S32 length = 0; char *pointer = NULL; char *line = NULL; if (NULL == context) { return NULL; } line = context->head_end; pointer = context->head_end; typedef struct _CONTEXT { S32 sock; /* 当前连接的会话套接字 */ U16 port; U32 timeout; /* 本链接的老化间。 */ char *host; char *if_none_match; char *if_modified_since; S32 async_buffer_len; /* 未完成发送的静态页面文件剩余长度。 */ S32 recv_count; /* 确认是否需要异步接收 */ S32 code; HTTP_MEDIA_TYPE media_type; BOOL disposition; S32 regard; struct sockaddr_in client; S32 (*parser)(struct _CONTEXT *context); HTTP_GROUP_SRV *group_srv; /* 初级用户组:根据 port 区分 */ void *onvif_soap; char *head_buf; char *content_buf; char *head_end; char *head_buf_end; char *hbuf_data_end; char *content_start; char *content_end; char *content_buf_end; char *boundary; char *platform; char *refer; /* 有session验证,暂不需要refer检查。 */ #if defined(INCLUDE_UPNP_SERVER) char *soap; /* HTTP扩展头部,用于UPnP。 */ char *man; /* HTTP扩展头部,用于UPnP。 */ char *callback; /* HTTP扩展头部,用于UPnP。 */ S32 sid_timeout; /* HTTP扩展头部,用于UPnP,订阅老化间,0表示无限。 */ char *sid; #endif char path[HTTP_URL_SIZE]; HTTP_ARG arg_list[HTTP_ARGLIST_SIZE]; S32 header_len; S32 content_len; #ifdef MAKEROOM_BEFORE_UPGRADE U32 precheck_len; BOOL precheck_ok; BOOL is_upgrade; #endif S32 post_handle_code; BOOL rsp_file; char rsp_file_path[HTTP_URL_SIZE * 2]; struct stat rsp_file_stat; HTTP_METHOD method; /* HTTP方法,GET/POST。 */ HTTP_VERSION version; /* HTTP版本,1.0/1.1 */ BOOL keepalive; /*是否使用持续连接*/ BOOL chunked; /*是否使用chunk传输*/ BOOL origin; /*是否存在Origin*/ BOOL done; /* 指名数据有无收完。 */ BOOL json; /* 表示请求是否是JSON请求 */ BOOL soap_xml; /* 表示请求是否是soap+xml请求 */ BOOL remove_first_boundary; /* 表示是否移除了第一个boundary */ HTTP_SESSION *session; char *key; char etag[HTTP_ETAG_SIZE]; char last_modified[HTTP_TIME_SIZE]; char passwd[USER_MANAGEMENT_PASSWD_MAX_STR_LEN]; char stok[HTTP_SESSION_SIZE]; U32 idle; DS_HANDLE_CONTEXT ds_context; BOOL is_https; void *ssl_ctx; S32 is_ssl_setfd; /* 是否设置fd到ssl结构体 */ /* 此标志位暂为了升级用,升级后必须重启,否则在http_reset_context等处造成内存泄漏 */ BOOL keep_forever; BOOL is_ssl_success; S32 ssl_handshake_num; BOOL is_http_header_parser_done; BOOL is_reserve; /* 保留context内容标志位 */ #ifdef LOCAL_PROTOCOL_SECURE S32 seq; BOOL seq_verify_fail; /* 头部解析seq解析失败 */ #endif }CONTEXT; ——详解一下代码,并说明如果我想要添加Digest认证该怎么修改
09-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值