Blocking TCP Connetion reads, but sends empty messages

rolobr
Posts: 7
Joined: Thu Feb 15, 2018 3:49 pm

Blocking TCP Connetion reads, but sends empty messages

Postby rolobr » Mon May 07, 2018 2:53 pm

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");
}

User avatar
fly135
Posts: 606
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: Blocking TCP Connetion reads, but sends empty messages

Postby fly135 » Mon May 07, 2018 5:52 pm

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");

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: Blocking TCP Connetion reads, but sends empty messages

Postby kolban » Mon May 07, 2018 6:08 pm

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?
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

User avatar
fly135
Posts: 606
Joined: Wed Jan 03, 2018 8:33 pm
Location: Orlando, FL

Re: Blocking TCP Connetion reads, but sends empty messages

Postby fly135 » Mon May 07, 2018 6:29 pm

Also if your write fails you close the listening socket, which makes no sense in the context of your code.

John

glrtheil
Posts: 61
Joined: Tue Dec 07, 2021 2:48 pm

Re: Blocking TCP Connetion reads, but sends empty messages

Postby glrtheil » Mon Mar 14, 2022 7:59 pm

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);
}

Who is online

Users browsing this forum: Google [Bot] and 98 guests