This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF9160 TCP connection, sending over LTE-M

Hello,

I'm trying to setup a TCP connection to a remote TCP echo server (echo.u-blox.com : 195.34.89.241, port 7), for testing.

The socket is being opened, and I receive a welcome message. However, it seems as if the connection is closed afterwards:

Sent: AT+CFUN=1
Received: OK

tcp_socket: 2
connect to 195.34.89.241 err: 0
Received: U-Blox AG TCP/UDP test service
 [31]
Sent: Hello U-Blox [Bytes: 13] [Error: 0]
Receive failed: [Bytes: 0] [Error: 0]
Send failed: 54
Receive failed: [Bytes: -1] [Error: 54]


With UDP, everything is working just fine. What am I missing?

The proj.conf:
#
# Copyright (c) 2019 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
#
# General config
CONFIG_ASSERT=y

# Network
CONFIG_NETWORKING=y
CONFIG_NET_NATIVE=n
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y

# BSD library
CONFIG_BSD_LIBRARY=y

# AT host library
CONFIG_AT_HOST_LIBRARY=y
CONFIG_UART_INTERRUPT_DRIVEN=y

# Stacks and heaps
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_HEAP_MEM_POOL_SIZE=32768

# Testing changes
CONFIG_GPIO=y

The code to set it up is as follows:

  printk("Starting socket\n");

  int at_socket_fd = socket(AF_LTE, SOCK_DGRAM, NPROTO_AT);

  if (at_socket_fd < 0)
  {
    printk("Socket err: %d, errno: %d\r\n", at_socket_fd, errno);
  }

  char *initCmds[1] = { "AT+CFUN=1" };
  send(at_socket_fd, initCmds[0], strlen(initCmds[0]), 0);
  printk("Sent: %s\n", initCmds[0]);

  recv(at_socket_fd, recv_buf, sizeof(recv_buf), 0);
  printk("Received: %s\n", recv_buf);

  k_msleep(15000);
  
  int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // SOCK_DGRAM, IPPROTO_UDP
  printk("tcp_socket: %i\n", tcp_socket);

  struct sockaddr_in remote_addr;
  remote_addr.sin_family = AF_INET;
  remote_addr.sin_port = htons(TCP_PORT);
  inet_pton(AF_INET, TCP_HOST, &(remote_addr.sin_addr));
  int err = connect(tcp_socket, (struct sockaddr *) &remote_addr, sizeof(remote_addr));
  printk("connect to %s err: %i\n", TCP_HOST, err);

  int bytes_received = recv(tcp_socket, recv_buf, sizeof(recv_buf), 0);
  if (bytes_received > 0)
  {
    printk("Received: %s [%i]\n", recv_buf, bytes_received);
  }
  else
  {
    printk("Receive failed: %i\n", errno);
  }

  for (;;)
  {
    memset(recv_buf, 0, sizeof(recv_buf));

    uint8_t cmd[] = "Hello U-Blox";
    
    int bytes_sent = send(tcp_socket, cmd, sizeof(cmd), 0);
    if (bytes_sent < 0)
    {
      printk("Send failed: %i\n", errno);
    }
    else
    {
      printk("Sent: %s [Bytes: %i] [Error: %i]\n", cmd, bytes_sent, errno);
    }

    bytes_received = recv(tcp_socket, recv_buf, sizeof(recv_buf), 0);
    if (bytes_received > 0)
    {
      printk("Received: %s [Bytes: %i]\n", recv_buf, bytes_received);
    }
    else
    {
      printk("Receive failed: [Bytes: %i] [Error: %i]\n", bytes_received, errno);
    }

    k_msleep(5000);
  }

  • Hello,

    What version of NCS are you using? It looks like the server is the issue here as it doesn't echo back. Attached is the main.c used in coap_client with added error handling just rename replace with main.c in the coap_client sample and rename to main.c

    /*
     * Copyright (c) 2019 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
     */
    
    #include <stdio.h>
    #include <string.h>
    
    #include <zephyr.h>
    #include <net/coap.h>
    #include <net/socket.h>
    #include <modem/lte_lc.h>
    #if defined(CONFIG_LWM2M_CARRIER)
    #include <lwm2m_carrier.h>
    #endif
    
    #define APP_COAP_SEND_INTERVAL_MS 5000
    #define APP_COAP_MAX_MSG_LEN 1280
    #define APP_COAP_VERSION 1
    
    static int sock;
    static struct pollfd fds;
    static struct sockaddr_storage server;
    static u16_t next_token;
    
    static u8_t coap_buf[APP_COAP_MAX_MSG_LEN];
    
    #if defined(CONFIG_BSD_LIBRARY)
    
    /**@brief Recoverable BSD library error. */
    void bsd_recoverable_error_handler(uint32_t err)
    {
    	printk("bsdlib recoverable error: %u\n", (unsigned int)err);
    }
    
    #endif /* defined(CONFIG_BSD_LIBRARY) */
    
    /**@brief Resolves the configured hostname. */
    static int server_resolve(void)
    {
    	int err;
    	struct addrinfo *result;
    	struct addrinfo hints = {
    		.ai_family = AF_INET,
    		.ai_socktype = SOCK_DGRAM
    	};
    	char ipv4_addr[NET_IPV4_ADDR_LEN];
    
    	err = getaddrinfo(CONFIG_COAP_SERVER_HOSTNAME, NULL, &hints, &result);
    	if (err != 0) {
    		printk("ERROR: getaddrinfo failed %d\n", err);
    		return -EIO;
    	}
    
    	if (result == NULL) {
    		printk("ERROR: Address not found\n");
    		return -ENOENT;
    	}
    
    	/* IPv4 Address. */
    	struct sockaddr_in *server4 = ((struct sockaddr_in *)&server);
    
    	server4->sin_addr.s_addr =
    		((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
    	server4->sin_family = AF_INET;
    	server4->sin_port = htons(CONFIG_COAP_SERVER_PORT);
    
    	inet_ntop(AF_INET, &server4->sin_addr.s_addr, ipv4_addr,
    		  sizeof(ipv4_addr));
    	printk("IPv4 Address found %s\n", ipv4_addr);
    
    	/* Free the address. */
    	freeaddrinfo(result);
    
    	return 0;
    }
    
    /**@brief Initialize the CoAP client */
    static int client_init(void)
    {
    	int err;
    
    	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    	if (sock < 0) {
    		printk("Failed to create CoAP socket: %d.\n", errno);
    		return -errno;
    	}
    
    	err = connect(sock, (struct sockaddr *)&server,
    		      sizeof(struct sockaddr_in));
    	if (err < 0) {
    		printk("Connect failed : %d\n", errno);
    		return -errno;
    	}
    
    	/* Initialize FDS, for poll. */
    	fds.fd = sock;
    	fds.events = POLLIN;
    
    	/* Randomize token. */
    	next_token = sys_rand32_get();
    
    	return 0;
    }
    
    /**@brief Handles responses from the remote CoAP server. */
    static int client_handle_get_response(u8_t *buf, int received)
    {
    	int err;
    	struct coap_packet reply;
    	const u8_t *payload;
    	u16_t payload_len;
    	u8_t token[8];
    	u16_t token_len;
    	u8_t temp_buf[16];
    
    	err = coap_packet_parse(&reply, buf, received, NULL, 0);
    	if (err < 0) {
    		printk("Malformed response received: %d\n", err);
    		return err;
    	}
    
    	payload = coap_packet_get_payload(&reply, &payload_len);
    	token_len = coap_header_get_token(&reply, token);
    
    	if ((token_len != sizeof(next_token)) &&
    	    (memcmp(&next_token, token, sizeof(next_token)) != 0)) {
    		printk("Invalid token received: 0x%02x%02x\n",
    		       token[1], token[0]);
    		return 0;
    	}
    
    	snprintf(temp_buf, MAX(payload_len, sizeof(temp_buf)), "%s", payload);
    
    	printk("CoAP response: code: 0x%x, token 0x%02x%02x, payload: %s\n",
    	       coap_header_get_code(&reply), token[1], token[0], temp_buf);
    
    	return 0;
    }
    
    /**@biref Send CoAP GET request. */
    static int client_get_send(void)
    {
    	int err;
    	struct coap_packet request;
    
    	next_token++;
    
    	err = coap_packet_init(&request, coap_buf, sizeof(coap_buf),
    			       APP_COAP_VERSION, COAP_TYPE_NON_CON,
    			       sizeof(next_token), (u8_t *)&next_token,
    			       COAP_METHOD_GET, coap_next_id());
    	if (err < 0) {
    		printk("Failed to create CoAP request, %d\n", err);
    		return err;
    	}
    
    	err = coap_packet_append_option(&request, COAP_OPTION_URI_PATH,
    					(u8_t *)CONFIG_COAP_RESOURCE,
    					strlen(CONFIG_COAP_RESOURCE));
    	if (err < 0) {
    		printk("Failed to encode CoAP option, %d\n", err);
    		return err;
    	}
    
    	err = send(sock, request.data, request.offset, 0);
    	if (err < 0) {
    		printk("Failed to send CoAP request, %d\n", errno);
    		return -errno;
    	}
    
    	printk("CoAP request sent: token 0x%04x\n", next_token);
    
    	return 0;
    }
    
    #if defined(CONFIG_LWM2M_CARRIER)
    K_SEM_DEFINE(carrier_registered, 0, 1);
    
    void lwm2m_carrier_event_handler(const lwm2m_carrier_event_t *event)
    {
    	switch (event->type) {
    	case LWM2M_CARRIER_EVENT_BSDLIB_INIT:
    		printk("LWM2M_CARRIER_EVENT_BSDLIB_INIT\n");
    		break;
    	case LWM2M_CARRIER_EVENT_CONNECT:
    		printk("LWM2M_CARRIER_EVENT_CONNECT\n");
    		break;
    	case LWM2M_CARRIER_EVENT_DISCONNECT:
    		printk("LWM2M_CARRIER_EVENT_DISCONNECT\n");
    		break;
    	case LWM2M_CARRIER_EVENT_READY:
    		printk("LWM2M_CARRIER_EVENT_READY\n");
    		k_sem_give(&carrier_registered);
    		break;
    	case LWM2M_CARRIER_EVENT_FOTA_START:
    		printk("LWM2M_CARRIER_EVENT_FOTA_START\n");
    		break;
    	case LWM2M_CARRIER_EVENT_REBOOT:
    		printk("LWM2M_CARRIER_EVENT_REBOOT\n");
    		break;
    	}
    }
    #endif /* defined(CONFIG_LWM2M_CARRIER) */
    
    /**@brief Configures modem to provide LTE link. Blocks until link is
     * successfully established.
     */
    static void modem_configure(void)
    {
    #if defined(CONFIG_LTE_LINK_CONTROL)
    	if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
    		/* Do nothing, modem is already turned on
    		 * and connected.
    		 */
    	} else {
    #if defined(CONFIG_LWM2M_CARRIER)
    		/* Wait for the LWM2M_CARRIER to configure the modem and
    		 * start the connection.
    		 */
    		printk("Waitng for carrier registration...\n");
    		k_sem_take(&carrier_registered, K_FOREVER);
    		printk("Registered!\n");
    #else /* defined(CONFIG_LWM2M_CARRIER) */
    		int err;
    
    		printk("LTE Link Connecting ...\n");
    		err = lte_lc_init_and_connect();
    		__ASSERT(err == 0, "LTE link could not be established.");
    		printk("LTE Link Connected!\n");
    #endif /* defined(CONFIG_LWM2M_CARRIER) */
    	}
    #endif /* defined(CONFIG_LTE_LINK_CONTROL) */
    }
    
    /* Returns 0 if data is available.
     * Returns -EAGAIN if timeout occured and there is no data.
     * Returns other, negative error code in case of poll error.
     */
    static int wait(int timeout)
    {
    	int ret = poll(&fds, 1, timeout);
    
    	if (ret < 0) {
    		printk("poll error: %d\n", errno);
    		return -errno;
    	}
    
    	if (ret == 0) {
    		/* Timeout. */
    		return -EAGAIN;
    	}
    
    	if ((fds.revents & POLLERR) == POLLERR) {
    		printk("wait: POLLERR\n");
    		return -EIO;
    	}
    
    	if ((fds.revents & POLLNVAL) == POLLNVAL) {
    		printk("wait: POLLNVAL\n");
    		return -EBADF;
    	}
    
    	if ((fds.revents & POLLIN) != POLLIN) {
    		return -EAGAIN;
    	}
    
    	return 0;
    }
    u8_t recv_buf[100];
    
    void main(void)
    {
    	s64_t next_msg_time = APP_COAP_SEND_INTERVAL_MS;
    	int err, received;
    
    	printk("The nRF CoAP client sample started\n");
    
    	modem_configure();
    	int tcp_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	printk("tcp_socket: %i\n", tcp_socket);
    
    	struct sockaddr_in remote_addr;
    	remote_addr.sin_family = AF_INET;
    	remote_addr.sin_port = htons(7);
    	inet_pton(AF_INET, "195.34.89.241", &(remote_addr.sin_addr));
    	err = connect(tcp_socket, (struct sockaddr *) &remote_addr, sizeof(remote_addr));
    	printk("connect err: %i\n", err);
    
    	for (;;)
    	{
    		char *cmd = "Hello U-Blox";
    		err = send(tcp_socket, cmd, strlen(cmd), 0);
    		printk("Sent %i bytes\n", err);
    		if (err < 0) {
    			printk("send() errno: %d\n", errno);
    		}
    
    		
    		err = recv(tcp_socket, recv_buf, sizeof(recv_buf), 0);
    		if (err == 0) {
    			printk("Received zero bytes, connection closed\n");		
    		} else if (err > 0) {
    			printk("Ret bytes: %d Received: %s\n", err, recv_buf);
    		} else {
    			printk("recv errno: %d\n", errno);
    		}
    
    		k_msleep(5000);
    	}
    }
    


    Please see this list with possible issues given by errno -1.

    Kind regards,
    Øyvind

  • Hi,

    I'm using NCS 1.3.0.
    Upon further investigation, the send() function returns 0, indicating no error, but still 0 bytes transmitted.

    I believe this means the socket is closed. Perhaps I should change modem / connection / socket options?
    Other connections from both my PC and another embedded device (other modem) do not have this problem.

  • I also tested UDP. This seems to work just fine. Funny thing though is, send() is returning 0 here as well. But the data is being echoed.

    TCP is still not working. I disabled power saving to make sure that nothing funny is happening there:

    AT+CEPPI=0
    AT+CPSMS=0
    AT+CEDRXS=0


    The socket seems to just get closed after receiving the initial data, resulting in error code ECONNRESET "Connection reset by peer":
    tcp_socket: 2
    connect to 195.34.89.241 err: 0
    Received: U-Blox AG TCP/UDP test service
     [31]
    Sent: Hello U-Blox [0]
    // -------------------------> Here there is a pause
    +CSCON: 0
    +CSCON: 1
    Receive failed: 0
    Send failed: 54
    Receive failed: 54


    I have also tried it with another server, same thing happens. Both servers are proven to work correctly when connecting from other devices.

  • I have edited the main post. I would appreciate your input!

  • Hello, 

    My apologies for the late reply. Difficult to see what you have altered in the main post, it's better to add changes as a comment to the thread. Can you please add prj.conf and main.c ?

    newUser said:
    ECONNRESET "Connection reset by peer":

    A connection reset by peer message means that the site you are connected to has reset the connection. This is usually caused by a high amount of traffic on the site, but may be caused by a server error as well.

    What other servers did you try?

Related