现在我正使用lwip的非阻塞socket作为tcp通信手段,然后在此过程中,进行https的ota操作,然后发现出现socket read fail问题 并且https也无法使用,若将当前socket关闭,则可以正常进行https升级,请问下有什么好的方法能解决此问题?(当前是wifi sta模式)
另外发现若采用以太网模式(不使用wifi,则https可以正常OTA,但是tcp还是会提示失败)
使用wifi log如下(tcp read 返回-9错误):
[0;32mI (46199) HXJ_OTA: Starting OTA example...[0m
[0;32mI (46199) HXJ_OTA: config.URL:https://file.hxjiot.com/firmware/C849A7 ... 18A870.bin[0m
[0;32mI (46209) HXJ_OTA: Running partition type 0 subtype 16 (offset 0x00080000)[0m
[0;32mI (46229) HXJ_TCPCLIENT: tcp错误errono=9[0m
[0;32mI (46229) HXJ_TCPCLIENT: tcp read failed
[0m
[0;31mE (46239) esp-tls: mbedtls_ssl_setup returned -0x7f00
[0m
[0;31mE (46249) esp-tls: Failed to open new connection[0m
[0;31mE (46249) TRANS_SSL: Failed to open a new connection[0m
[0;31mE (46249) HTTP_CLIENT: Connection failed, sock < 0[0m
[0;32mI (46259) HXJ_OTA: HTTP_EVENT_DISCONNECTED[0m
[0;31mE (46259) HXJ_OTA: Failed to open HTTP connection: ESP_ERR_HTTP_CONNECT[0m
[0;31mE (46269) HXJ_OTA: Firmware Upgrades Failed[0m
[/code]
使用以太网 log如下 (一开始进行https,则tcp read马上返回 -9错误)
Code: Select all
[0;32mI (17869) HXJ_OTA: Starting OTA example...[0m
[0;32mI (17869) HXJ_OTA: config.URL:https://file.hxjiot.com/firmware/C849A7A10470000151FB14E91918A870.bin[0m
[0;32mI (17879) HXJ_OTA: Running partition type 0 subtype 16 (offset 0x00080000)[0m
[0;32mI (17899) HXJ_TCPCLIENT: tcp错误errono=9[0m
[0;32mI (17899) HXJ_TCPCLIENT: tcp read failed
[0m
[0;32mI (18969) HXJ_OTA: HTTP_EVENT_ON_CONNECTED[0m
[0;32mI (18989) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Server, value=Tengine[0m
[0;32mI (18989) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Content-Type, value=application/octet-stream[0m
[0;32mI (18989) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Content-Length, value=1015536[0m
[0;32mI (18999) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Connection, value=keep-alive[0m
[0;32mI (19009) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Date, value=Fri, 11 Jan 2019 04:21:14 GMT[0m
[0;32mI (19009) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Accept-Ranges, value=bytes[0m
[0;32mI (19019) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Access-Control-Allow-Origin, value=*[0m
[0;32mI (19029) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Access-Control-Expose-Headers, value=X-Log, X-Reqid[0m
[0;32mI (19039) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Access-Control-Max-Age, value=2592000[0m
[0;32mI (19049) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Cache-Control, value=public, max-age=31536000[0m
[0;32mI (19059) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Content-Disposition, value=inline; filename="C849A7A10470000151FB14E91918A870.bin"; filename*=utf-8' 'C849A7A10470000151FB14E91918A870.bin[0m
[0;32mI (19069) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Content-Transfer-Encoding, value=binary[0m
[0;32mI (19079) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Etag, value="F[0m
[0;32mI (19089) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Last-Modified, value=Wed, 09 Jan 2019 08:47:51 GMT[0m
[0;32mI (19099) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=X-Log, value=redis.g/404;mc.g/404;redis.g;rs40_shard.sel:5;rwro.get:5;RS.dbs:5;RS:5;redis.s;1s.gh:27;PFDS:28;IO:37[0m
[0;32mI (19109) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=X-M-Log, value=QNM:xs459;SRCPROXY:xs485;SRC:37;SRCPROXY:37;QNM3:40[0m
[0;32mI (19119) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=X-M-Reqid, value=PSoAAFphsNFxsHgV[0m
[0;32mI (19129) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=X-Qiniu-Zone, value=0[0m
[0;32mI (19139) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=X-Qnm-Cache, value=Miss[0m
[0;32mI (19149) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=X-Reqid, value=rVIAAMnh3tFxsHgV[0m
[0;32mI (19149) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=X-Svr, value=IO[0m
[0;32mI (19159) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Ali-Swift-Global-Savetime, value=1547180474[0m
[0;32mI (19169) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Via, value=cache35.l2su18-2[184,200-0,M], cache36.l2su18-2[186,0], vcache5.cn627[0,200-0,H], vcache7.cn627[1,0][0m
[0;32mI (19179) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Age, value=10843[0m
[0;32mI (19189) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=ache, value=HIT TCP_MEM_HIT dirn:12:155996968[0m
[0;32mI (19199) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=X-Swift-SaveTime, value=Fri, 11 Jan 2019 04:21:15 GMT[0m
[0;32mI (19209) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=X-Swift-CacheTime, value=2592000[0m
[0;32mI (19219) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=Timing-Allow-Origin, value=*[0m
[0;32mI (19219) HXJ_OTA: HTTP_EVENT_ON_HEADER, key=EagleId, value=7909f64715471913177701228e[0m
[0;32mI (19229) HXJ_OTA: HTTP_EVENT_ON_DATA, len=195[0m
[0;32mI (19239) HXJ_OTA: Starting OTA...[0m
[0;32mI (19239) HXJ_OTA: Writing to partition subtype 17 at offset 0x240000[0m
[0;32mI (20699) HXJ_OTA: esp_ota_begin succeeded[0m
[0;32mI (20699) HXJ_OTA: Please Wait. This may take time[0m
[0;32mI (20709) HXJ_OTA: HTTP_EVENT_ON_DATA, len=317[0m
[0;32mI (20709) HXJ_OTA: Written image length 512[0m
[0;32mI (20709) HXJ_OTA: HTTP_EVENT_ON_DATA, len=512[0m
[0;32mI (20719) HXJ_OTA: Written image length 1024[0m
[0;32mI (20719) HXJ_OTA: HTTP_EVENT_ON_DATA, len=512[0m
[0;32mI (20729) HXJ_OTA: Written image length 1536[0m
[0;32mI (20729) HXJ_OTA: HTTP_EVENT_ON_DATA, len=59[0m
[0;32mI (20739) HXJ_OTA: HTTP_EVENT_ON_DATA, len=453[0m
非阻塞tcp实现代码如下:
Code: Select all
/*==============================================================================
* Function: new_tcp_read()
* Description: 非阻塞tcp读取
* Input: none
* Return: none
* Others: none
*============================================================================*/
static int new_tcp_read(int tcp_fd, unsigned char* buf, unsigned short len)
{
int ret = -1;
if(buf == NULL)
{
return -1;
}
/*TCP读取数据需要判断错误码*/
ret = (int)(recv(tcp_fd, buf, len, MSG_DONTWAIT));
if(ret <= 0)
{
if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
{
return 0;//OK
}
else
{
ESP_LOGI(TAG,"tcp错误errono=%d",errno);
return -1;
}
}
return ret;
}
/*==============================================================================
* Function: new_tcp_state()
* Description: 非阻塞tcp设置参数
* Input: none
* Return: none
* Others: none
*============================================================================*/
static int new_tcp_state(int sock)
{
int errcode = 0;
int tcp_fd = sock;
if(tcp_fd < 0) {
return -1;
}
#if 1
fd_set rset, wset;
int ready_n;
FD_ZERO(&rset);
FD_SET(tcp_fd, &rset);
wset = rset;
struct timeval timeout;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
/*使用select机制判断tcp连接状态*/
ready_n = select(tcp_fd + 1, &rset, &wset, NULL, &timeout);
if(0 == ready_n)
{
ESP_LOGI(TAG,"select time out\n");
errcode = -1;
}
else if(ready_n < 0)
{
ESP_LOGI(TAG,"select error\n");
errcode = -1;
}
else
{
// ESP_LOGI(TAG,"FD_ISSET(tcp_fd, &rset):%d\n FD_ISSET(tcp_fd, &wset):%d\n",
// (int)FD_ISSET(tcp_fd, &rset) , (int)FD_ISSET(tcp_fd, &wset));
// test in linux environment,kernel version 3.5.0-23-generic
// tcp server do not send msg to client after tcp connecting
int ret;
socklen_t len = sizeof(int);
if(0 != getsockopt (tcp_fd, SOL_SOCKET, SO_ERROR, &ret, (socklen_t*)&len))
{
ESP_LOGI(TAG,"getsocketopt failed\r\n");
errcode = -1;
}
// ESP_LOGI(TAG,"getsocketopt ret=%d errno %d\r\n",ret, errno);
if(0 != ret)
{
ESP_LOGI(TAG,"getsocketopt ret=%d errno %d\r\n",ret, errno);
errcode = -1;
}
}
#endif
int ret;
socklen_t len = sizeof(int);
if(0 != getsockopt (tcp_fd, SOL_SOCKET, SO_ERROR, &ret, (socklen_t*)&len))
{
ESP_LOGI(TAG,"getsocketopt failed\r\n");
errcode = -1;
}
// ESP_LOGI(TAG,"getsocketopt ret=%d errno %d\r\n",ret, errno);
if(0 != ret)
{
ESP_LOGI(TAG,"getsocketopt ret=%d errno %d\r\n",ret, errno);
errcode = -1;
}
return errcode;
}
/*==============================================================================
* Function: new_tcp_send()
* Description: 非阻塞tcp发送
* Input: none
* Return: none
* Others: none
*============================================================================*/
int new_tcp_send(int tcp_fd, const unsigned char* buf, unsigned short len)
{
int ret = -1;
if(buf == NULL)
{
return -1;
}
/*TCP发送数据需要判断错误码*/
ret = (int)(send(tcp_fd, buf, len, MSG_DONTWAIT));
if(ret < 0)
{
if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
{
return 0;
}
else
{
return -1;
}
}
ESP_LOGI(TAG,"new_tcp_send=%d",ret);
return ret;
}
static int new_tcp_connect(in_addr_t srcip,const char* dst, unsigned short port)
{
struct sockaddr_in servaddr;
int tcp_fd;
int flags;
int reuse;
if(NULL == dst)
{
return -1;
}
tcp_fd = socket(AF_INET, SOCK_STREAM, 0);
if(tcp_fd < 0)
{
ESP_LOGI(TAG,"creat socket tcp_fd failed\n");
return -1;
}
/*设置非阻塞模式*/
flags = fcntl(tcp_fd, F_GETFL, 0);
if(flags < 0 || fcntl(tcp_fd, F_SETFL, flags | O_NONBLOCK) < 0)
{
ESP_LOGI(TAG,"fcntl: %s\n", strerror(errno));
close(tcp_fd);
return -1;
}
reuse = 1;
if(setsockopt(tcp_fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &reuse, sizeof( reuse ) ) != 0 )
{
close(tcp_fd);
ESP_LOGI(TAG,"set SO_REUSEADDR failed\n");
return -1;
}
memset(&servaddr, 0, sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(dst);
servaddr.sin_port = htons(port);
struct sockaddr_in src;
memset(&src,0,sizeof(struct sockaddr_in));
src.sin_addr.s_addr = srcip;//使用sta的 ip
src.sin_family = AF_INET;
src.sin_port=htons(10000);
//destAddr.sin_port = htons(PORT);
//绑定一下 ip
//bind(tcp_fd,&src,sizeof(struct sockaddr));
if(connect(tcp_fd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)) == 0)
{
return tcp_fd;
}
else
{
if(errno == EINPROGRESS)
{
ESP_LOGI(TAG,"tcp conncet noblock\n");
return tcp_fd;
}
else
{
close(tcp_fd);
return -1;
}
}
}
Code: Select all
tcp_fd = new_tcp_connect( (in_addr_t)sta_ip.ip.addr,Host, Port);
//recv_len为1024
if(new_tcp_state(tcp_fd)!= 0)
{
ESP_LOGI(TAG,"tcp not connect\n");
break;
// continue;
}
else
{
ESP_LOGI(TAG,"tcp connect successuflly\n");
tcp_connect_flag = 1;
}
while(1)
{
//省略发送等其他逻辑
recv_len = new_tcp_read(tcp_fd, tcp_reveive_buffer, tcp_max_size-1);
if(recv_len > 0)
{
ESP_LOGI(TAG,"recv data:%s,length:%d\n", tcp_reveive_buffer, recv_len);
InterNet_Receive((char *)&tcp_reveive_buffer,recv_len);
clilenttcp_get_answer=1;
}
else if(recv_len == 0)
{
// ESP_LOGI(TAG,"recv no data\n");
// continue;
}
else
{
ESP_LOGI(TAG,"tcp read failed\n");
break;
}
vTaskDelay(30 / portTICK_PERIOD_MS);//每30ms读取1K数据
}
//TCP失败到此
谢谢!!!!!!