This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/CC3220S-LAUNCHXL:具有保持活动功能的 HTTP 客户端(simplelink 2.20.0.10)

Guru**** 2549840 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/wi-fi-group/wifi/f/wi-fi-forum/739501/ccs-cc3220s-launchxl-http-client-with-keep-alive-simplelink-2-20-0-10

器件型号:CC3220S-LAUNCHXL

工具/软件:Code Composer Studio

大家好、  

想知道是否有使用 HTTP 1.1保持活动功能的示例项目? 查看 httpclient.c 中的 sendRequest 和 HttpClient_connect 代码、只要未调用 HttpClient_disconnect、它就像应在保持活动模式下工作一样。 这是正确的、还是需要执行其他操作(如设置其他请求标头)?

其他一些相关问题。

 -我在随后调用 HttpClient_connect 时收到错误-3013 (客户端已连接)。 想知道是否可以在后续请求中保留此呼叫、但只需忽略此错误并继续请求?

 -我在同一主机地址有多个端点,但端点使用的 AUTH 有2种不同类型。 如果我使用永久性标头、是否应确保在调用具有不同 AUTH 类型和机密的 HttpClient_setHeader 之前删除之前设置的 AUTH 标头、或者在我第二次调用 HttpClient_setHeader 时、AUTH 类型和机密是否会被覆盖?

感谢您对此问题的任何帮助、提前感谢您!

哈沙

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Harsha、

    1) 1)在调用 HttpClient_setHeader()时,可以通过'HttpClient_HFIELD_persistent'标志设置保持活动。 请查阅《网络服务 API 指南》、了解有关该指南的更多信息: dev.ti.com/.../

    2) 2)关于错误-3013、您可以根据您尝试执行的操作而忽略它、但这意味着您的新连接未发生。 如果您希望两个连接到同一台服务器,则应该能够使用不同的句柄。

    3) 3)在 httpclient.c 中、如果选项类型相同、则会覆盖该选项。 但是,在将 HttpClient_getHeader()设置为双检查后,始终可以使用它。

    此致、
    Kristen
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢 Kristen! 下面是一些答复
    1) 1)我已将某些标头配置为 PERSISTENT、这将使它们都保持不变。 网络服务 API 实际上除了声明使用标志会使标头持续还是不持续之外、并不能提供太多信息、这对于添加有关这如何帮助支持持久 HTTP 连接的注释可能很有用

    2) 2) Gotcha、我将使用2个单独的句柄、并向您更新它的运行方式

    3)很好、谢谢。

    我想让这个线程保持活动状态(不打算使用 pun!) 因此、如果我本周遇到问题、我可以提出更多问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Kristen、

    我现在能够通过多个请求保持 HTTP 连接。 感谢您的帮助。

    不过、我确实看到了一个问题。 我的应用程序旨在每秒发出一次 GET 请求。 事实证明、在调用 HttpClient_readResponseBody 函数时、应用程序经常被阻止。 此函数调用 SlNetSock_recv -看起来此调用的执行被阻止、该调用在60秒后超时并以0字节读取返回。 有关此行为的几个问题

    1) 1)您是否碰巧知道导致 slNetSock_recv 超时的原因?

    2) 2)我是否可以更改此超时持续时间?

    期待再次收到您的回复、谢谢。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Harsha、

    请参阅下面链接的帖子、其中描述了阻塞套接字以及如何更改超时。

    e2e.ti.com/.../681806

    此致、
    Kristen
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢 Kristen。 我使用该帖子来配置接收超时、但收到了 slNetSock_SETOPT API 的-2006错误。 是否有一个文件/文档可供我参考以了解错误代码的含义?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您可以在中找到错误代码 /source/ti/net/slneterr.h

    此致、
    Kristen
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    找到它、错误代表

    /*参数无效*/
    #define SLNETERR_RET_CODE_INVALID_INPUT (-2006L)

    这是我的代码、我不太理解我通过的任何输入有什么问题。 您能找出我遗漏的任何内容吗? (请注意、我将此代码添加到 HttpClient_create 函数中、并且只有在创建的客户端"cli"有效、HTTP_CLIENT_RECV_TIMEOUT_s 的当前值为1秒时才会执行此代码)

    //设置接收超时
    struct slNetSock_Timeval_t timeVal;
    timeVal.tv_sec = HTTP_CLIENT_RECV_TIMEOUT_s;
    timeVal.tv_usec = 0;
    RET = SlNetSock_SETOPT (CLI_>ssock、SLNETSOCK_LVL_Socket、SLNETSOCK_OPSOCK_RCV_Timeo、(void*)&timeVal、sizeof (SlNetSock_Timeval_t));

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我尝试的其他 SlNetSock_SETOPT 调用也会看到相同的错误、一个用于设置 SLNETSOCK_OPSOCK_KEEPALIVE、另一个用于设置 SLNETSOCK_OPSOCK_KEEPALIVE。 我使用了 slnetsock.h 注释中提供的示例代码

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Harsha、

    我刚刚验证了以下代码是否正常工作(它基于 HttpGet 示例(附带 setsockopt)。
    唯一需要验证的是“cli->ssssock”的有效性。


    BR、
    Kobi

    如果(NULL == SD)

    RetVal = SlNetSock_create (serverAddr.sa_family、SLNETSOCK_SOCK_STREAM、SLNETSOCK_PROTO_TCP、
    ifBitmap、0);
    virtualSd = RetVal;


    if (0 <= virtualSd)

    struct slNetSock_Timeval_t timeVal;
    timeVal.tv_sec = 1;//秒
    timeVal.tv_usec = 0;//微秒。 10000微秒分辨率
    RetVal = SlNetSock_SETOPT (virtualSd、SLNETSOCK_LVL_Socket、SLNETSOCK_OPSOCK_RCV_RCV_Timeo、
    (uint8_t *)&timeVal、sizeof (timeVal);//启用接收超时

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢 Kobi。
    我猜此代码片段来自 SlNetSock_connectURI。
    我将尝试在该位置添加我的套接字选项、并让您知道具体情况。

    更大的问题是-设置持久 HTTP 连接需要做什么? Kristen 回答说、我需要做的就是将标题设置为 persistent。 不确定这是否对我有效。 如果您知道需要执行的其他步骤、请告诉我。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Harsha、

    好的。 请告诉我接收超时设置。
    PERSISTENT 似乎只是将服务器的 TCP 连接关闭延迟一段时间(通常在10-15秒之间、具体取决于服务器)、以允许您在现有连接上发送其他 HTTP 请求。
    如果 HTTP 请求之间的时间间隔较长、则需要定期重新发送此消息。
    邮件之间的间隔是多少?
    为了降低功耗、您可能希望始终关闭连接。

    BR、
    Kobi
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我目前正在将 RECV 超时设置为5秒。
    当您说"此消息"时、您是否指的是 TCP 保持活动数据包? 我认为默认情况下、它设置为每5分钟发送一次到服务器。
    您建议将其设置为什么?

    另外,我也不清楚“10-15秒取决于服务器”的含义。 在 HTTP 客户端级别,只要请求包含“连接:保持活动”报头,并且只要服务器在响应中发送相同的报头,就应调用所需的 TCP 机制来保持连接活动。 我的问题本质上是、我需要在 HTTP 客户端级别执行什么操作来确保这种情况发生。 进行了比较
    1.每个请求都会在报头中发送“连接:保持活动”
    2.我相信服务器会以相同的标头进行响应
    3.我已将所有标头设置为永久性

    还需要什么来确保连接保持活动状态?

    由于重新协商每个请求的 TLS 握手所产生的延迟、关闭每个请求的连接对我们来说不是一个选项。 该器件已插入交流电源、因此功耗不是问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    根据我的理解、PERSISTENT 取代了保持活动(HTTP 1.1的一部分)。
    即使您发送具有持久性的请求,HTTP 服务器也会在10-15秒后断开连接。
    这与 TCP 保持活动无关、而是与(HTTP)应用级别的某些看门狗相关。
    您需要在服务器看门狗过期之前发送另一个请求。

    BR、
    Kobi
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Kobi、
    通过此链接 - www.w3.org/.../rfc2616-sec8.html 、很明显、如果客户端发送保持活动连接标头、HTTP 1.1服务器必须保持开放连接、因此服务器端看门狗似乎不太可能、因为我在响应标头中看到服务器支持 HTTP 1.1。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的。 我不确定这一点。

    simplelink 端目前是否有任何阻止您的东西?

    BR、

    Kobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    嗯、我被以下方法所阻止:没有使用 simplelink 包附带的 Http 客户端模块使用持久 HTTP 连接的方法。 您能与能够提供帮助的人联系吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这话什么意思。 我想 Kristen 已经回答了这个问题(在第一个回答中)。 缺少什么?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    当我将标头设置为 persistent 时、客户端在持久 HTTP 模式下的行为与其预期不同。 因此、似乎还有其他事情需要做、或者需要按照特定顺序完成才能使其正常工作。 我的请求是与熟悉 HttpClient 模块工作原理以及如何利用其 API 使我的器件在持久模式下工作的人员取得联系(为了清晰明了、 这是指使用相同的连接发出多个请求、而无需在请求之间断开连接)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    只需向我们提供有关 您所做的工作和失败位置的确切详细信息(您要连接到的服务器、请求之间的持续时间等)。 请发送日志(终端+监听器)和错误代码。

    BR、

    Kobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    早上好、Kobi、

    这里是我要执行的操作的伪代码

    ------------------------------------------------------------------

    //函数发送 HTTP 请求
    http_request (http_handle、AUTH_type、secret、request_method、URI、 数据、RESPONSE_BUF){
      if (http_handle == NULL){
        http_handle = HttpClient_create()
        get_hostname()
        HttpClient_connect (http_handle、主机名...)
      }

      //使用 HttpClient_setHeader 设置标头
      Set_auth_header (http_handle、AUTH_type、secret、persistent)
      Set_Keep_Alive_header(HTTP_Handle、persistent)

      //使用 HttpClient_sendRequest 发送请求
      SEND_REQUEST (HTTP_Handle、Request_method、URI、数据、RESPONSE_BUF)

      //过程响应
      if (NULL!= RESPONSE_BUF){
        PROCESS_RESPONSE (RESPONSE_BUF)
      }


    //应用程序
    while (connected 至_WLAN){
      http_request(....)
      睡眠(五秒)

    ------------------------------------------------------------------

    在上面的伪代码中,get_hostname()返回格式 为 harsha-test.device-test.com 的字符串

    一个示例 URI 是/things-to-do/device-id

    当应用程序运行时、我看到第一次调用 http_request 时、该请求会正常运行、但每次后续调用都会导致错误-3021、该错误定义为  

    *当未找到主机标头时、只能建立重新连接
    *具有绝对 URI。
    *
    #define HttpClient_ENOTABSOLUTEURI (-3021)

    因此、我修改了 http_request 函数以添加主机标头(值=  "="">https://harsha-test.device-test.com) as shown below, but I still get the same -3021 error.

    ---------------------------------------------------------------------------------------------------------------

    // function to send HTTP request
    http_request (HTTP_HANDLE, AUTH_TYPE, SECRET, REQUEST_METHOD, URI, DATA, RESPONSE_BUF) {

        if(HTTP_HANDLE == NULL) {
            HTTP_HANDLE = HTTPClient_create()
            get_hostname() 
            HTTPClient_connect(HTTP_HANDLE, hostname, ....)
        } else {
            set_host_header(HOSTNAME_WITHOUT_PROTOCOL)
        }


        // set headers using HTTPClient_setHeader
        set_auth_header(HTTP_HANDLE, AUTH_TYPE, SECRET, PERSISTENT)
        set_keep_alive_header(HTTP_HANDLE, PERSISTENT)

        // send request using HTTPClient_sendRequest
        send_request(HTTP_HANDLE, REQUEST_METHOD, URI, DATA, RESPONSE_BUF)

        // process response
        if(NULL != RESPONSE_BUF) {
            process_response(RESPONSE_BUF)
        }

    }

    ---------------------------------------------------------------------------------------------------------------

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Harsha、

     HttpClient_connect 是否成功返回(即返回代码为0)?

    BTW。 我已经使用标准 HTTP 服务器(例如 google.com)进行了检查、它们通常不会根据客户端请求更新保持活动超时(google.com 会在5秒后终止"持久"连接)。   

    BR、

    Kobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Kobi、

    是的、HttpClient_connect 返回0、并且服务器成功接收到我的第一个请求。 以下请求(之前没有连接)似乎得到-3021错误。 此时、我似乎可以通过对后续请求使用绝对 URI (主机名+ URI)来使-3021消失、但似乎服务器没有接收到我的请求。 运行更多的测试来确定这一点、将使您保持更新。

    同时、如果您可以查看我正在执行的操作(从伪代码)的顺序、并让我知道这是否看起来正常、这将会很有帮助。

    谢谢。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Harsha、

    您能否发送"set_host_header()"的实现?
    伪代码似乎正确、因此需要更好地了解故障原因。
    但请注意、无论如何、我们讨论的是服务器在第二次请求之前断开设备连接的情况、因此它仍将涉及整个 TLS 连接设置。 已终止的连接在 SendRequest 中标识,该请求在不通知用户的情况下触发重新连接。

    BR、
    Kobi
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Kobi,在我的最新实施中,我不使用"set_host_header()",而只使用完整的 URI 和主机名。 这似乎摆脱了-3021。 但现在我从端点获得了状态400、我怀疑这是由于格式错误的请求。 以下是请求发送的所有部分的日志。

    我已经用-----------------注释了某些记录行。 因此我可以对它们进行评论
    答:这是建立 TLS 连接的位置
    B:直到这一点,操作似乎是正常的(看起来有重试,因此它发出了两次)
    C:这是预期的,如果您注意到 Bearer auth 标头,则标记为空,设备上电时就会出现这种情况。 因此、我们从服务器获得401 (未经授权)、这是预期的、之后、设备应向身份验证端点发出具有已知机密的请求、以获取 Bearer 令牌。 这发生在 D 点
    D-E:似乎可以,这些是我们在请求中需要的有效标头
    F-G:这似乎是导致问题的原因。 为什么要发送来自前一个请求的不记名股票的授权? FW 通过调用具有 NULL 值的 HttpClient_setHeader 来确保删除任何剩余的 Auth 令牌。 尽管如此,看起来以前的授权令牌正在发出。 这绝对是一个问题
    GH:主机标头已设置、因此未显示-3021错误
    I:从服务器获取状态400
    --------------------------------------------------------------------

    WLAN 事件] STA 连接到 AP:kudoornet
    [NetApp 事件] IP 192.168.43.189,网关192.168.43.1
    --获取设备 OPS --
    |1/1|--创建新的 HTTP 句柄-- ------------------ A
    Uri (66)=/devices/abcdefghijklmnopqrstuvwz/operations/?status=new (max-age=30s)
    sendBuf =获取/devices/abcdefghijklmnopqrstuvwz/operations/?status=new 最大年龄=30s HTTP/1.1
    sendBuf =连接:保持活动
    sendBuf =授权:承载
    sendBuf =主机:master.my-domain.com
    sendBuf =
    sendBuf =获取/devices/abcdefghijklmnopqrstuvwz/operations/?status=new 最大年龄=30s HTTP/1.1
    sendBuf =连接:保持活动
    sendBuf =授权:承载
    sendBuf =主机:master.my-domain.com
    sendBuf =
    cloud_comms_http_request:Non-Success HTTP Status - 401 ------------------ B
    cloud_comms_get_device_operations:无效的授权令牌-获取新的授权令牌 ------------------ C
    auth_token (61)= a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18
    Uri (42)= master.my-domain.com/authenticate
    sendBuf = POST master.my-domain.com/authenticate HTTP/1.1 ------------------ D
    sendBuf =连接:保持活动
    sendBuf =授权:基本 a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18 ------------------ e
    sendBuf =连接:保持活动 -------------------- F
    sendBuf =授权:承载 -------------------- G
    sendBuf =主机:master.my-domain.com -------------------- h
    sendBuf =
    cloud_comms_http_request:Non-Success HTTP Status - 400 -------------------- 一

    --------------------------------------------------------------------