Shalom!
I am getting with the nRF9160, BSD TCP sockets, a connect() errno=116 after disconnecting and closing a previous TCP connection.
I have two TCP servers with the same IP just different ports. When I switch to the second one, I get this error. I can connect at startup to the second server so the problem is not with the server.
What am I doing wrong?
I use set the socket SO_RCVTIMEO to 30000 so that when closing the previous server the blocking call to blocking_recv() will return.
I had thought, that if I had not set the socket receive timeout, that closing the socket would cause the recv() call to return but this is not the case, so I set the timeout.
#define CONFIG_DOWNLOAD_CLIENT_TCP_SOCK_TIMEO_MS 30000
Below is my connection snippet.
Thanks
//-----------------------------------------------------------------------------
// Flag to indicate if a disconnect has been requested.
//-----------------------------------------------------------------------------
static atomic_t disconnect_requested;
static int app_socket_fd = -1;
...
//-----------------------------------------------------------------------------
// ami_socket_get_disconnect_requested
// Description
//
// Parameters
// Returns
//
//-----------------------------------------------------------------------------
bool ami_socket_get_disconnect_requested(void)
{
return (bool)atomic_get(&disconnect_requested);
} // ami_socket_get_disconnect_requested
//-----------------------------------------------------------------------------
// blocking_recv
// Description
//
// Parameters
// Returns
//
//-----------------------------------------------------------------------------
int blocking_recv(int fd, u8_t *buf, u32_t size, u32_t flags)
{
int err;
do{
err = recv(fd, buf, size, flags);
}while ((err<0) && (errno==EAGAIN) && !ami_socket_get_disconnect_requested());
return err;
} // blocking_recv
//-----------------------------------------------------------------------------
// blocking_send
// Description
//
// Parameters
// Returns
//
//-----------------------------------------------------------------------------
static int blocking_send(int fd, u8_t *buf, u32_t size, u32_t flags)
{
int err;
do{
err = send(fd, buf, size, flags);
}while ((err<0) && (errno==EAGAIN) && !ami_socket_get_disconnect_requested());
return err;
} // blocking_send
//-----------------------------------------------------------------------------
// ami_main_SendBinaryData
// Description
// Tries to send the bianry data over the connection
// Parameters
// buf
// len
// Returns
// true if sent
//-----------------------------------------------------------------------------
bool ami_socket_SendBinaryData(const unsigned char *buf,uint16_t len)
{
int err = blocking_send(app_socket_fd,(u8_t *)buf, len, 0);
if (err < 0) {
d_printf(LINE_INFO,kDbg_Error|kDbg_General,"TX Fail:%d", errno);
}
return (err==0);
} // ami_socket_SendBinaryData
//-----------------------------------------------------------------------------
// blocking_connect
// Description
//
// Parameters
// Returns
// 0 = OK
//-----------------------------------------------------------------------------
static int blocking_connect(int fd, struct sockaddr *local_addr, socklen_t len)
{
int err;
do{
err = connect(fd, local_addr, len);
}while ((err<0) && (errno==EAGAIN) && !ami_socket_get_disconnect_requested());
return err;
} // blocking_connect
//-----------------------------------------------------------------------------
// socket_timeout_set
// Description
//
// Parameters
// Returns
// 0 = OK
//-----------------------------------------------------------------------------
static int socket_timeout_set(int fd, int type)
{
int err;
uint32_t timeout_ms;
if (type == SOCK_STREAM) {
timeout_ms = CONFIG_DOWNLOAD_CLIENT_TCP_SOCK_TIMEO_MS;
}else{
timeout_ms = CONFIG_DOWNLOAD_CLIENT_UDP_SOCK_TIMEO_MS;
}
if (timeout_ms <= 0) {
return 0;
}
struct timeval timeo = {
.tv_sec = (timeout_ms / 1000),
.tv_usec = (timeout_ms % 1000) * 1000,
};
d_printf(LINE_INFO,kDbg_Info|kDbg_General,"SocketTimeout:%lds", timeo.tv_sec);
err = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));
if (err){
d_printf(LINE_INFO,kDbg_Error|kDbg_General,"SocketTimeoutErr:%d", errno);
return -errno;
}
return 0;
} // socket_timeout_set
//-----------------------------------------------------------------------------
// connect_to_cloud
// Description
// Tries to connect to the Cloud
// Parameters
// Returns
// ami_socket_connect_result
//-----------------------------------------------------------------------------
static int connect_to_cloud(void)
{
atomic_set(&disconnect_requested, 0);
struct sockaddr local_addr;
int err;
char sIPPort[24];
sprintf(sIPPort,"%u.%u.%u.%u:%u",
cur_server.server_ip.bytes[MSB_HI_BYTE],
cur_server.server_ip.bytes[MSB_LO_BYTE],
cur_server.server_ip.bytes[LSB_HI_BYTE],
cur_server.server_ip.bytes[LSB_LO_BYTE],
cur_server.server_port.word
);
//---------------------------------------------------------------------------
// Parse the IP:Port string
//---------------------------------------------------------------------------
if (!net_ipaddr_parse((const char *)sIPPort,strlen(sIPPort),&local_addr)){
d_printf(LINE_INFO,kDbg_Error|kDbg_General,"ServerIP:PortParsingErr");
return AMI_SOCKET_CONNECT_RES_ERR_NOT_INITD;
}
//---------------------------------------------------------------------------
// Close socket if opened
//---------------------------------------------------------------------------
if (app_socket_fd>=0){
close(app_socket_fd);
}
//---------------------------------------------------------------------------
// Create a TCP socket
//---------------------------------------------------------------------------
app_socket_fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
d_printf(LINE_INFO,kDbg_Info|kDbg_General,"SocketFD:%d",app_socket_fd);
//---------------------------------------------------------------------------
// Set socket timeout
//---------------------------------------------------------------------------
err = socket_timeout_set(app_socket_fd,SOCK_STREAM);
if (err) {
d_printf(LINE_INFO,kDbg_Info|kDbg_General,"SetSockTimeoutErr:%d", errno);
return err;
}
//---------------------------------------------------------------------------
// Connect
//---------------------------------------------------------------------------
err = blocking_connect(app_socket_fd, (struct sockaddr *)&local_addr,sizeof(struct sockaddr_in));
if (errno){
err = errno;
d_printf(LINE_INFO,kDbg_Info|kDbg_General,"ConnectionErr:%d %s",errno,sIPPort);
}else
d_printf(LINE_INFO,kDbg_Info|kDbg_General,"Connected:%s",sIPPort);
return err;
} // connect_to_cloud