您好!
我根据网络终端和云 OTA 示例为 CC3220SF LAUNCHXL 编写了一个程序。
该方案的工作方式如下:
1.计算机上运行的客户端程序通过 WiFi 连接到 LaunchPad 服务器套接字并向设备发送命令
2. Launchpad 解码命令并通过 UART 将命令传输到器件
该器件通过 UART 对命令做出响应
4. Launchpad 通过 WiFi 加密数据并将其传输到客户端程序
当只有一个 LaunchPad 连接时、该程序工作稳定、至少一天内没有重新连接。
当有多个连接时、客户端程序会定期重新连接到 LaunchPad。
连接客户端程序的新副本时,重新连接会变得更加频繁。
一段时间后、某种稳定和重新连接变得不太频繁。
连接客户端程序的另一个副本时、情况会重复出现。
如果我删除一行 usleep(1000);在 for (i=0;i<16; i++)之后,重新连接的数量会急剧增加。
如果在1秒内服务器没有响应、客户端程序将重新连接。
当 有多个连接时,为什么客户端程序正在重新连接?
Code Composer Studio 10.2.0、SimpleLink CC32xx SDK 4.30.00.06
以下是我有关 WiFi 数据交换的源代码:
int32_t TCPServerInit(sockAddr_t *sAddr, uint16_t port)
{
int32_t sock;
int32_t status;
int32_t nonBlocking = TRUE;
/* Contains the local ip address and port */
SlSockAddr_t *sa;
int32_t addrSize;
/* filling the TCP server socket address */
sAddr->in4.sin_family = SL_AF_INET;
/* Set the server's port:
We'll receive connection requests on this port */
sAddr->in4.sin_port = sl_Htons(port);
sAddr->in4.sin_addr.s_addr = SL_INADDR_ANY;
sa = (SlSockAddr_t*)sAddr;
addrSize = sizeof(SlSockAddrIn_t);
/*
* Open a TCP socket:
* Since TCP is a connection oriented channel,
* the opened socket would serve as 'welcome' socket,
* on which we'll receive connection requests from clients.
*/
sock = sl_Socket(sa->sa_family, SL_SOCK_STREAM, TCP_PROTOCOL_FLAGS);
ASSERT_ON_ERROR(sock, SL_SOCKET_ERROR);
/* Bind socket to server's port */
status = sl_Bind(sock, sa, addrSize);
if(status < 0)
{
UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
SL_SOCKET_ERROR);
sl_Close(sock);
return(-1);
}
/* 'Listen' signify that wer'e ready to receive connection's from clients */
status = sl_Listen(sock, 0);
if(status < 0)
{
UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
SL_SOCKET_ERROR);
sl_Close(sock);
return(-1);
}
/* Set socket as non-blocking socket (if needed):
* Non-blocking sockets allows user to handle other tasks rather than block
* on socket API calls.
* If an API call using the Non-blocking socket descriptor
* returns 'SL_ERROR_BSD_EAGAIN' -
* this indicate that the user should try the API again later.
*/
nonBlocking = TRUE;
status =
sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlocking,
sizeof(nonBlocking));
if(status < 0)
{
UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
SL_SOCKET_ERROR);
return(-1);
}
return sock;
}
typedef union
{
uint32_t ipv4; /* Ipv4 Address */
uint8_t ipv6[16]; /* Ipv6 Address */
}ip_t;
SlSockAddr_t *IP2SlSockAddr(uint8_t sl_fa, uint16_t portNumber, ip_t ipAddress, sockAddr_t *sAddr)
{
// filling the TCP server socket address
sAddr->in4.sin_family = SL_AF_INET;
// Since this is the client's side,
// we must know beforehand the IP address
// and the port of the server wer'e trying to connect.
sAddr->in4.sin_port = sl_Htons((unsigned short)portNumber);
sAddr->in4.sin_addr.s_addr = sl_Htonl((unsigned int)ipAddress.ipv4);
return (SlSockAddr_t*)sAddr;
}
int32_t TCPClientInit(uint8_t sa_family)
{
int32_t sock;
int32_t status;
int32_t nonBlocking;
// Get socket descriptor - this would be the
// socket descriptor for the TCP session.
sock = sl_Socket(sa_family, SL_SOCK_STREAM, TCP_PROTOCOL_FLAGS);
ASSERT_ON_ERROR(sock, SL_SOCKET_ERROR);
// Set socket as non-blocking socket (if needed):
// Non-blocking sockets allows user to handle
// other tasks rather than block
// on socket API calls.
// If an API call using the Non-blocking socket descriptor
// returns 'SL_ERROR_BSD_EAGAIN' -
// this indicate that the user should try the API again later.
nonBlocking = TRUE;
status = sl_SetSockOpt(sock, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlocking, sizeof(nonBlocking));
if(status < 0)
{
UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, status,
SL_SOCKET_ERROR);
sl_Close(sock);
return(-1);
}
return sock;
}
void *appThread(void *arg0)
{
uint8_t run_first = 1;
int32_t server_sock;
/* Contains the ip address and port of the connected peer. */
static SlSockAddr_t *csa;
static sockAddr_t sAddr;
static int32_t addrSize;
int32_t ret;
uint32_t ans;
int32_t newsock = -1;
static uint8_t server_states[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t *psrvstate;
uint32_t uart_send_size;
uint32_t *pusendsz;
#define server_state *psrvstate
static uint32_t socket_sizes[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t *psocksz;
#define socket_size *psocksz
static uint32_t socket_flags[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t *psockfl;
#define socket_flag *psockfl
int32_t status;
static int32_t client_socks[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int32_t *pclsock;
static uint8_t client_states[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t *pclstate;
#define client_sock *pclsock
#define client_state *pclstate
uint8_t queue_state;
uint16_t queue_size;
uint8_t *queue_bufptr;
static uint8_t queue_items[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
#define queue_item queue_items[i]
...
while(1)
{
usleep(1000);
if(run_first)
{
server_sock = TCPServerInit(&sAddr, 2612);
csa = (SlSockAddr_t*)&sAddr;
addrSize = sizeof(SlSockAddrIn_t);
if(server_sock >= 0)
run_first = 0;
}
else
{
newsock = sl_Accept(server_sock, csa, (SlSocklen_t*)&addrSize);
if(newsock == SL_ERROR_BSD_EAGAIN)
{
//break;
}
else if(newsock < 0)
{
server_states[newsock] = 0;
}
else
{
UART_PRINT("Connected to client %d: ", newsock);
sAddr.in4.sin_addr.s_addr = sl_Htonl(sAddr.in4.sin_addr.s_addr);
PrintIPAddress(FALSE,(void*)&sAddr.in4.sin_addr);
UART_PRINT(lineBreak);
if(newsock < 16)
{
server_states[newsock] = 1;
}
}
uint8_t i = 0;
for(i = 0; i < 16; i++)
{
usleep(1000);
socketBuf = sockbuf[i];
psrvstate = &server_states[i];
psocksz = &socket_sizes[i];
psockfl = &socket_flags[i];
switch(server_state)
{
case 0:
// Not connected
break;
case 1:
ret = sl_Recv(i, socketBuf, MAX_BUF_SIZE, 0);
if(ret == SL_ERROR_BSD_EAGAIN)
{
break;
}
else if(ret < 0)
{
UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, ret,
BSD_SOCKET_ERROR);
UART_PRINT("Socket %d closed\n\r", i);
sl_Close(i);
server_state = 0;
break;
}
else if(ret == 0)
{
UART_PRINT("TCP Client (socket %d) closed the connection \n\r", i);
sl_Close(i);
server_state = 0;
break;
}
uart_send_size = ret;
queue_item = AddToQueue(socketBuf, uart_send_size, socketBuf, 0);
server_state = 2;
break;
case 2:
queue_state = QueueState(queue_item);
if(queue_state >= ready)
{
queue_size = QueueSize(queue_item);
socket_size = queue_size;
}
else
break;
case 3:
Encrypt((char*)socketBuf, (char*)socketBuf, socket_size);
ret = sl_Send(i, socketBuf, socket_size, 0);
if(ret == SL_ERROR_BSD_EAGAIN)
{
break;
}
else if(ret < 0)
{
UART_PRINT("[line:%d, error:%d] %s\n\r", __LINE__, ret,
SL_SOCKET_ERROR);
UART_PRINT("Socket %d closed\n\r", i);
sl_Close(i);
server_state = 0;
break;
}
server_state = 1;
break;
}
}
}
}
}
此外、文件 cloud_ota.c 中函数[CheckLanConnection]的[1531]行有时会出现错误错误[-2]
第1531行对应于代码
/* Ping the GW */
retVal = sl_NetAppPing((SlNetAppPingCommand_t*)&pingParams, \
SL_AF_INET, (SlNetAppPingReport_t*)&pingReport, \
SimpleLinkPingReport);
ASSERT_ON_ERROR(retVal);
尝试更新时、程序很少会在 cloud_ota.c 文件中的 loop_forever ()行上挂起
if(NULL != pEntry->p_evtHndl)
{
if(pEntry->p_evtHndl() < 0)
{
UART_PRINT("Event handler failed..!! \r\n");
LOOP_FOREVER();
}
}