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