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

NRF9160 BSD socket "send function" isn't blocked.

I use BSD socket to send and receive messages to a TCP server over LTE network.

When I send multiple messages by using send() (with flags = 0) function, I get an EINPROGRESS error.
It seems that send() function is not blocked.


I'm currently using the v1.1.0 release.

How can I fix this problem?

Parents
  • Hi,

     

    There are certain use-cases where send() isn't blocking, which are mentioned in the changelog:

    http://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrfxlib/bsdlib/doc/CHANGELOG.html

     

    Could you share the routine that you're running?

     

    Kind regards,

    Håkon

  • ERROR_STATUS blocking_send(int sock, u8_t *buf, u32_t datalen, u32_t flags, uint32_t timeout)
    {
         u32_t offset = 0U;
         int ret;
         s64_t time_stamp = k_uptime_get();
         s64_t milliseconds_spent = 0;

         while ((offset < datalen)&&(milliseconds_spent <timeout))
                 {
                     ret = send(sock, buf + offset,
                                        MIN(4096, (datalen - offset)), flags);
                     if (ret < 0)
                        {
                            return -errno;
                         }

                        offset += ret;
                       milliseconds_spent += k_uptime_delta(&time_stamp);
                 }
           if(milliseconds_spent >= timeout)
                  return STATUS_TIMEOUT;
           return 0;
    }

  • Hi,

     

    If the socket is configured as non-blocking with setsockopt(), you can get EINPROGRESS back. This can also occur if another sequence is on-going, like getaddrinfo(), or when the memory is full for prior bsdlib versions (but, then you should get another return code), or the buffer size is too high. Are you using zephyr minimal libc, or newlibc? The errno.h is different on those. Could you post the raw errno that you are getting?

    Is this TLS based communication? If yes, then the buffer size should be reduced to max. 2k

    Kind regards,

    Håkon

  • I am using default library (minimal libc) and setsockopt is not used.

    My purpose is to send 50KB buffer to remote tcp server, currently without TLS, so the buffer is full.
    As I understand, there is no other process in background.
    (Can I send 50KB buffer with single tcp packet?)

    Meni

  • Hi,

     

    A UDP packet has a length field of 16 bits, so the theoretical max length is just shy of 64k. However, you are limited here by the maximum size of the bsdlib, which is 4k, as defined in bsd_limits.h::BSD_IP_MAX_MESSAGE_SIZE, so you'll have to split it into chunks.

    And on the IP layer It'll again be split into chunks (MTU size is normally 1280 bytes), but reassembled on the other end again.

    What is the raw errno-number that is returned?

    Is this behavior consistent, ie; it always happens?

     

    Kind regards,

    Håkon

Reply
  • Hi,

     

    A UDP packet has a length field of 16 bits, so the theoretical max length is just shy of 64k. However, you are limited here by the maximum size of the bsdlib, which is 4k, as defined in bsd_limits.h::BSD_IP_MAX_MESSAGE_SIZE, so you'll have to split it into chunks.

    And on the IP layer It'll again be split into chunks (MTU size is normally 1280 bytes), but reassembled on the other end again.

    What is the raw errno-number that is returned?

    Is this behavior consistent, ie; it always happens?

     

    Kind regards,

    Håkon

Children
  • errono 119, and It always happens (even with newlibc).

    Meni

  • Could this be due to a former socket operation that is on-going?

    What happens if you treat EINPROGRESS as a EAGAIN, ie: you try to send the same data again?

     

    Kind regards,

    Håkon

  • No, It does not work.
    The only way it works is when I add a delay after send command.

    Meni

  • Hi,

     

    I am very sorry for the late feedback.

    You mention that you send and receive. Do you have other threads running modem traffic in your firmware?

    Could you provide an example so I can try to recreate this at my end and debug further?

     

    Kind regards,

    Håkon

  • Hi,

    No, I have only one thread that uses the modem.

    Attached is a source code that describes this thread.

    Meni

    ERROR_STATUS server_connect(uint8_t* url, uint16_t port, int *client_fd)
    {
      ERROR_STATUS err_state;
      err_state = modem_configure();
      if(err_state)
        return err_state; 
    
      struct addrinfo *res;
    
      int err = getaddrinfo(url, NULL, NULL, &res);
      
      printk("getaddrinfo err: %d\n\r", err);
      if(err)
        return STATUS_URL_ERROR;
    
      ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(port);
      struct sockaddr_in local_addr;
    
      local_addr.sin_family = AF_INET;
      local_addr.sin_port = htons(0);
      local_addr.sin_addr.s_addr = 0;
    
      *client_fd = socket(AF_INET, SOCK_STREAM, 0);
      printk("client_fd: %d\n\r", *client_fd);
    
      err = bind(*client_fd, (struct sockaddr *)&local_addr, sizeof(local_addr));
      
      if(err)
      {
        printk("bind err: %d\n\r", err);
        return STATUS_CONNECTION_ERROR;
        }
    	
      err = connect(*client_fd, (struct sockaddr *)res->ai_addr, sizeof(struct sockaddr_in));
      
      
      if(err < 0)
      {
        printk("connect err: %d\n\r", errno);
        return STATUS_CONNECTION_ERROR;
      }
      freeaddrinfo(res);
      printk("connected to server\n\r");
      return STATUS_NO_ERROR;
    }
    
    ERROR_STATUS blocking_send(int sock, u8_t *buf, u32_t datalen, u32_t flags, uint32_t timeout)
    {
       u32_t offset = 0U;
       volatile static int ret;
       s64_t  time_stamp = k_uptime_get();
       s64_t  milliseconds_spent = 0;
    
       while ((offset < datalen)&&(milliseconds_spent <timeout))
       {
          ret = send(sock, buf + offset,
                     MIN(4096, (datalen - offset)), flags);
          if (ret < 0)
          {
             return -errno;
          }
    
          offset += ret;
          milliseconds_spent += k_uptime_delta(&time_stamp);
       }
      if(milliseconds_spent >= timeout)
              return STATUS_TIMEOUT;
       return 0;
    }
    
    ERROR_STATUS blocking_recv(int fd, u8_t *buf, u32_t size, u32_t flags, uint32_t timeout)
    {
            volatile static int err;
            s64_t  time_stamp = k_uptime_get();
            s64_t  milliseconds_spent = 0;
    	do {
    		err = recv(fd, buf, size, flags);
    
                    k_sleep(10);                  
    
                    milliseconds_spent +=  k_uptime_delta(&time_stamp);
              } while ((err <= 0)&&(milliseconds_spent<timeout));
           
    
           if (err < 0)       
           {
              printk("recv socket err: %d, errno: %d\r\n", err, errno);
              return err;
            }
            if(milliseconds_spent >= timeout)
              return STATUS_TIMEOUT;
     
           return STATUS_NO_ERROR;
    }
    
    static void server_thread_fn(void *arg1, void *arg2, void *arg3)
    {
    	int client_fd;
        while(true)
            {          
                k_msgq_get(&xServerQueue, &task_com, K_FOREVER);
    		  
    			uint8_t* buffer = k_malloc(9000);
    			memset(buffer,0,9000);
    			server_connect(url,port,&client_fd);
    			blocking_send(client_fd,buffer,9000,0,60000);
    			blocking_recv(client_fd,buffer,9000,0,60000);
    			close(client_fd);
    			
    		}
    }

Related