Page 1 of 1

Blocking TCP Connetion reads, but sends empty messages

Posted: Mon May 07, 2018 2:53 pm
by rolobr
Hello,
I would like to use a blocking tcp socket to first receive messages an then send a message after I got a message.
The blocking receiver works fine but the sender is only sending two empty tcp messages.
If I set "fcntl(cs,F_SETFL,O_NONBLOCK);" instead of "fcntl(cs,F_SETFL,0);" receiving and sending works fine but is not blocking anymore like I would like to have it.

It would be really nice if you could help me.

In the following you find my tcp socket code.

Thank you very much in advance :-)

Code: Select all

void tcp_server(void *pvParam){
	static char messageReceived[100];
	bool messageReceivedIni = false;
    ESP_LOGI(tag,"tcp_server task started \n");
    struct sockaddr_in tcpServerAddr;
    tcpServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    tcpServerAddr.sin_family = AF_INET;
    tcpServerAddr.sin_port = htons( UNICAST_PORT );
    int s, r;
    char recv_buf[64];
    static struct sockaddr_in remote_addr;
    static unsigned int socklen;
    socklen = sizeof(remote_addr);
    int cs;//client socket
    xEventGroupWaitBits(wifi_event_group,CONNECTED_BIT,false,true,portMAX_DELAY);
    while(1){
        s = socket(AF_INET, SOCK_STREAM, 0);
        if(s < 0) {
            ESP_LOGE(tag, "... Failed to allocate socket.\n");
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(tag, "... allocated socket\n");
         if(bind(s, (struct sockaddr *)&tcpServerAddr, sizeof(tcpServerAddr)) != 0) {
            ESP_LOGE(tag, "... socket bind failed errno=%d \n", errno);
            close(s);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }
        ESP_LOGI(tag, "... socket bind done \n");
        if(listen (s, 2) != 0) { //Number of pending connections
            ESP_LOGE(tag, "... socket listen failed errno=%d \n", errno);
            close(s);
            vTaskDelay(4000 / portTICK_PERIOD_MS);
            continue;
        }
        while(1){
            cs=accept(s,(struct sockaddr *)&remote_addr, &socklen);
            ESP_LOGI(tag,"New connection request,Request data:");
          
            //fcntl(cs,F_SETFL,O_NONBLOCK);
            fcntl(cs,F_SETFL,0);

            bzero(recv_buf, sizeof(recv_buf)); 
            r = recv(cs, recv_buf, sizeof(recv_buf)-1,0);
            while(r > 0)
            {
            	if(messageReceivedIni == false)
            	{
            		strncpy(messageReceived, recv_buf,r);
            		messageReceivedIni = true;
            	}
            	else
            	{
            		strncat(messageReceived, recv_buf,r);
            	}

            	printf("Mess: %s Buf: %s", messageReceived, recv_buf);
               	bzero(recv_buf, sizeof(recv_buf)); 
            	r = recv(cs, recv_buf, sizeof(recv_buf)-1,0); 
            }


            ESP_LOGI(tag, "... done reading from socket. Last read return=%d errno=%d\r\n", r, errno); //Always returns r=0, errno=128. 128 is not written in the lwip documentation.

            char message[100] = "abcdweffaaerfawefwefwefawf";
            if( write(cs , message , strlen(message)) < 0) //Is evaluated as false, but only two empty tcp messages are sent to the receiver!
            {
                ESP_LOGE(tag, "... Send failed \n");
                close(s);
                vTaskDelay(4000 / portTICK_PERIOD_MS);
                continue;
            }
            ESP_LOGI(tag, "... socket send success");  //Is written out
            close(cs);
        }
        ESP_LOGI(tag, "... server will be opened in 5 seconds");
        vTaskDelay(5000 / portTICK_PERIOD_MS);
    }
    ESP_LOGI(tag, "...tcp_client task closed\n");
}

Re: Blocking TCP Connetion reads, but sends empty messages

Posted: Mon May 07, 2018 5:52 pm
by fly135
Not sure exactly what you are asking, but sounds like you need a timeout.

Code: Select all

if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
                sizeof(timeout)) < 0)
        error("setsockopt failed\n");

Re: Blocking TCP Connetion reads, but sends empty messages

Posted: Mon May 07, 2018 6:08 pm
by kolban
Just a wild guess ... but in your code, perhaps change your call to "write()" to a call to "send()". While I fully understand your use of "write" which is great on Unix, I question if "write" is correct on ESP32? We know that "send()" works ... maybe test with that?

Re: Blocking TCP Connetion reads, but sends empty messages

Posted: Mon May 07, 2018 6:29 pm
by fly135
Also if your write fails you close the listening socket, which makes no sense in the context of your code.

John

Re: Blocking TCP Connetion reads, but sends empty messages

Posted: Mon Mar 14, 2022 7:59 pm
by glrtheil
I could not get the above example from fly135 to work, but I eventually figured it out using timeval

In this example, the delay is 1ms (1000us). I'm looking to only process what might be in an rx buffer. It is necessary to set tv_sec to 0 in order to set something lower than 1 second.

Code: Select all

//make receive calls nonblocking
struct timeval tm;
tm.tv_sec = 0;
tm.tv_usec = 1000;

int err = setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &tm, sizeof(tm));
if (err < 0)
{
    ESP_LOGE(TAG, "setsockopt failed. error: %d", err);
}