最近,我一直在使用德州仪器(TI)的MSP430F5529微控制器和CC3100网络处理器从事IoT项目。为了进行评估,我使用了MSP430F5529发射台和CC3100 Boosterpack。我正在尝试使设备连接到云。我已经成功实现了CC3100获取天气示例应用程序,该应用程序连接到www.openweathermap.org。此示例来自CC3100 SDK示例应用程序。该程序成功从www.openweathermap.org网站接收并回复。该应用程序使用GET方法从网站发出请求。

我也已经针对www.mocky.io成功地测试了该代码。设备收到状态码200 OK响应。但是,当我在测试站点中对requestb.test进行测试时,没有得到408超时错误响应代码或302的URL重定向响应代码。

 #define WEATHER_SERVER  "api.openweathermap.org"
#define TEST_SERVER  "requestb.in"
//#define TEST_SERVER  "www.mocky.io"

#define PREFIX_BUFFER   "GET /data/2.5/weather?q="
#define POST_BUFFER     "&APPID=xxxxxxxxxxxxxxxxxx&mode=xml&units=imperial HTTP/1.1\r\nHost:api.openweathermap.org\r\nAccept: */"
#define POST_BUFFER2    "*\r\n\r\n"

#define PREFIX_BUFFER_TEST    "GET /1m75pgt1"
#define POST_BUFFER_TEST_1    " HTTP/1.1\r\nHost:requestb.in\r\nAccept: */"
#define POST_BUFFER_TEST_2    "\r\n\r\n"*

//#define PREFIX_BUFFER_TEST      "GET /v2/5967a65d1100007d16b6c2b4"
//#define POST_BUFFER_TEST_1    " HTTP/1.1\r\nHost:www.mocky.io\r\nAccept: */"
//#define POST_BUFFER_TEST_2    "\r\n\r\n"*
 


下面是主要内容,其中包括一些设置条件。为简便起见,已删除了一些错误处理代码。

  int main(int argc, char** argv)
{
    _i32 retVal = -1;

    retVal = initializeAppVariables();
    ASSERT_ON_ERROR(retVal);



    /* Stop WDT and initialize the system-clock of the MCU */
    stopWDT();
    initClk();


    /*
     * Following function configures the device to default state by cleaning
     * the persistent settings stored in NVMEM (viz. connection profiles &
     * policies, power policy etc)
     *
     * Applications may choose to skip this step if the developer is sure
     * that the device is in its default state at start of application
     *
     * Note that all profiles and persistent settings that were done on the
     * device will be lost
     */
    retVal = configureSimpleLinkToDefaultState();


    /*
     * Assumption is that the device is configured in station mode already
     * and it is in its default state
     */
    retVal = sl_Start(0, 0, 0);

    /* Connecting to WLAN AP */
    retVal = establishConnectionWithAP();

    retVal = getCredentials();

    retVal = disconnectFromAP();

    return 0;
}
 


下面是调用获取数据的getCredentials()代码。

<!-- language: lang-c -->
static _i32 getCredentials()
{
    _i32 retVal = -1;

    pal_Strcpy((char *)g_DeviceData.HostName, TEST_SERVER);

    retVal = getHostIP_Device();

    g_DeviceData.SockID = createConnection();
    ASSERT_ON_ERROR(g_DeviceData.SockID);

    retVal = getData();
    ASSERT_ON_ERROR(retVal);

    retVal = sl_Close(g_DeviceData.SockID);
    ASSERT_ON_ERROR(retVal);

    return 0;
}


下面是出现错误的getdata()函数。

 /*!
    \brief This function Obtains the required data from the server

    \param[in]      none

    \return         0 on success, -ve otherwise

    \note

    \warning
*/
static _i32 getData()
{
    _u8 *p_startPtr = NULL;
    _u8 *p_endPtr = NULL;
    _u8* p_bufLocation = NULL;
    _i32 retVal = -1;

    pal_Memset(g_DeviceData.Recvbuff, 0, sizeof(g_DeviceData.Recvbuff));

    /* Puts together the HTTP GET string. */
    p_bufLocation = g_DeviceData.SendBuff;

    pal_Strcpy(p_bufLocation, PREFIX_BUFFER_TEST);
    p_bufLocation += pal_Strlen(PREFIX_BUFFER_TEST);

    pal_Strcpy(p_bufLocation, POST_BUFFER_TEST_1);
    p_bufLocation += pal_Strlen(POST_BUFFER_TEST_1);

    pal_Strcpy(p_bufLocation, POST_BUFFER_TEST_2);

    /* Send the HTTP GET string to the open TCP/IP socket. */
    retVal = sl_Send(g_DeviceData.SockID, g_DeviceData.SendBuff, pal_Strlen(g_DeviceData.SendBuff), 0);
    if(retVal != pal_Strlen(g_DeviceData.SendBuff))
        ASSERT_ON_ERROR(HTTP_SEND_ERROR);

    /* Receive response */
    retVal = sl_Recv(g_DeviceData.SockID, &g_DeviceData.Recvbuff[0], MAX_SEND_RCV_SIZE, 0);
    if(retVal <= 0)
        ASSERT_ON_ERROR(HTTP_RECV_ERROR);

    g_DeviceData.Recvbuff[pal_Strlen(g_DeviceData.Recvbuff)] = '#define SEC_TYPE        SL_SEC_TYPE_WPA_WPA2    /* Security type of the Access point */
';
    return SUCCESS;
}
 


接入点的安全性设置为

 q4312079q 


最后,很少有用CC3100制造的POC传感器设备需要将数据传输到云中。为简单起见,我们使用boosterpack,最终我们需要使POC传感器设备通过Wifi与云通信。

评论

我投票结束这个问题是因为离题,因为该问题的实际问题是关于基本的HTTP使用,而在较小程度上是特定的嵌入式平台,而不是物联网,因此,通用性是其他HTTP问题首先,完全没有其他物联网问题。

仅供参考,您代码中的特定requestb.in实例显然已超时,现在通过SNI通过TLS通过HTTP访问HTTP时现在为404,适用于当前有效的请求。

@mico,我注意到您已删除答案。您还提到了在http中添加“ s”。我不确定如何实现您的建议。能否请您给我一些见解。

@ChrisStratton,很抱歉听到您投票关闭此问题。您能推荐我一个好的问答网站来问这个问题吗?

您是否收到302和408消息?如果没有,那么您收到什么消息?

#1 楼

区别在于,requestb.in网站要求使用SNI的TLS上的HTTP。

这是一个相当复杂的HTTP / HTTPS协议,安全性问题可能会在SE系统的其他地方得到更好的解决,并且主要涉及到您正在测试的requestb.in服务,而不是您最终可能要执行的任何IoT项目。但是只要它保留在这里...


在端口80上尝试HTTP时调试requestb.in响应代码

您说:


但是,当我在测试站点中对requestb。进行测试时,我没有得到408超时错误响应代码或URL重定向响应代码302。


让我们看看会发生什么:

curl -i http://requestb.in/xxxxxxxx
HTTP/1.1 301 Moved Permanently
Location: https://requestb.in/xxxxxxxx


HTTP状态301为“永久移动”,而您期望的302有时用于临时重定向。由于他们可能不打算让您在端口80上的纯TCP套接字上使用HTTP,因此,他们发送的永久重定向是更正确的响应。

如果您已经捕获了_was_发送的状态代码,而不仅仅是列出了_wesnot_发送的状态代码

无论如何,服务器告诉我们必须使用HTTPS。


那么,通过HTTPS连接到服务器需要做什么?

从根本上来说,HTTPS只是意味着通过受TLS(或更早的SSL)保护的连接说HTTP,而不是通过普通的TCP套接字执行此操作。

您的CC3100支持TLS和SSL,并且有关修改SDK的一个HTTP客户端示例以通过建立安全通道来执行HTTPS连接的信息很少,有关详细信息,请访问http://processors.wiki。 .ti.com / index.php / CC3100_HTTP_Client

但是,对于requestb.in,这可能还不够。

如果您要将非常简单的GET请求通过管道传递到openssl的s_client命令中(或在CC3100上执行相同的操作)

(echo -en "GET /xxxxxxxx HTTP/1.1\nHost: requestb.in\n\n" ; sleep 10) | \
openssl s_client -connect requestb.in:443


sleep是让openssl等待响应而不是在输入结束时挂断)

您会得到一个奇怪的错误:


SSL例程:SSL23_GET_SERVER_HELLO:sslv3警报握手失败


您可能认为这与SSL和TLS版本有关,但这实际上是因为requestb.in需要称为服务器名称指示(Wikipedia)。这实际上意味着您需要告诉SSL堆栈以告诉服务器它应将其认证为哪个服务器名。

继续进行命令行演示,我们只需添加一个-servername参数:

(echo -en "GET /xxxxxxxx HTTP/1.1\nHost: requestb.in\n\n" ; sleep 10) |\
openssl s_client -connect requestb.in:443 -servername requestb.in


如果使用URL哈希完成有效的requestb.in实例,它会产生一个结果,并且在创建该结果的浏览器的日志面板中可见。


在CC3xxx上实现服务器名称指示(SNI)

有一些论坛帖子建议CC3xxx上的TLS实现不支持SNI,并且没有具体的计划来添加它。但是,您可以验证情况是否仍然如此。

但是重要的是要记住,其中涉及一棵网络层树:

WiFi
  IP packets
    TCP session
      TLS session
        HTTP protocol


由于CC3100允许您说TCP(实际上您已经在现有代码中讲了),因此您可以自由地“自带”具有SNI支持的TLS实现。例如,此博客文章讨论了将mbed TLS(以前的PolarSSL)库移植到CC3xxx,并提到了SNI作为功能。

TL; DR

requestb.in是一个具有挑战性的目标,因为它要求您在通过TLS保护并实现服务器名称指示的会话上说HTTP。如果与该主机的对话不是您最终项目的一部分,您可能会发现最好直接转到那些主机-那些旨在与IoT设备上的最少嵌入式客户端一起使用的主机可能会通过以下方式进行配置,使事情变得容易一些不使用SNI。

如果习惯于捕获遇到的问题的详细信息,效率也会大大提高-嵌入式开发总是很难调试,而有关失败的信息也就更少通过日志记录或调试器捕获,花费的时间更多。

评论


看起来不错的答案,但超出了我的理解范围。我希望在不久的将来达到这种深度的知识水平。但是,非常感谢您的答复。

–user8055
17年7月25日在15:20

SNI要求的确确实使它变得复杂-我的建议是跳过requestb.in,专注于您在实际项目中实际尝试与之交谈的要求,并在必要时找到更类似于以下内容的模拟服务:那个要求。

–克里斯·斯特拉顿(Chris Stratton)
17年7月25日在16:09



现在,当阅读此内容时,并删除了我的两个竞争性工作后,我建议您做同样的事情,以提高工作效率。并且接受克里斯的努力。

–mico
17年7月25日在17:23



#2 楼

openweathermap.org和www.mocky.io都很可能支持http或端口80。以下是一些线索。

openweathermap.org





www.mocky.io





看起来像requestb.in仅支持HTTPS或端口443。

requestb.in





这可能解释了问题。以下是一些可能有用的参考。

在CC3100数据表中,没有对使用HTTPS的CC3100的引用。所有参考仅针对HTTP。这可能更好地解释了这个问题。在数据表的例外项下面附加一个数据。



每个数据表都类似CC3120支持HTTPS。下面的附件是数据表中的内容。对HTTPS的引用很少。



最可能的发展途径是用CC3120代替CC3100。

参考文献:


接受GET / Post调用的HTTP测试服务器
宣布Httpbin.org
CC3100 SimpleLink™Wi-Fi®网络处理器
CC3120 SimpleLink™Wi-Fi®无线网络处理器
CC3100 HTTP服务器


评论


经过无数次编辑引入错误并加以纠正之后,现在可能正在成为一个实际的答案。但是您实际上仍然需要重写它:如果您的论点是一个站点支持http,而另一个站点仅支持https,则只需在前面说一下即可。

–克里斯·斯特拉顿(Chris Stratton)
17年7月22日在15:06



而且您对CC3100和替换建议的分析仍然完全错误。它明确表示它支持TLS / SSL,而当您试图通过与服务器无关的问题来错误地查看它的Web服务器功能时,则表示它不支持。问题实际上是根本没有使用HTTP库,而是在TCP套接字上手动进行操作。要联系HTTPS服务器,它需要在SSL连接上执行类似的操作。

–克里斯·斯特拉顿(Chris Stratton)
17年7月22日在15:11