Page 1 of 1

[solved] can't accept new connection from listen socket second time

Posted: Thu Nov 03, 2016 10:39 am
by engelant
EDIT: It's solved in the meantime, just works now as expecetd

every time when I post something like this, I really hope I'm not the cause of this issue. Unfortunatly I'm not working with sockets that often. And I haven't used lwip before, so I'don't know where my troubles are coming from.

This is some code, I can run locally, it works as expected. Only one connection can be served at a time, but once it's done, the next one will get accepted.

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

const static char http_html_hdr[] =
                "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";

int main() {
        int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        printf("New sock = %d\n", sock);

        struct sockaddr_in serverAddress;
        serverAddress.sin_family = AF_INET;
        serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
        serverAddress.sin_port = htons(80);
        int rc = bind(sock, (struct sockaddr * ) &serverAddress,
                        sizeof(serverAddress));

        printf("bind completed! %d\n", rc);

        rc = listen(sock, 10);
        printf("listen completed! %d\n", rc);


        struct sockaddr_in clientAddress;
        socklen_t clientAddressLength = sizeof(clientAddress);
        int newsockfd, n;
        char buffer[256];
        while (1) {
                printf("Waiting connection accept\n");
                newsockfd = accept(sock, (struct sockaddr * ) &clientAddress,
                                &clientAddressLength);
                printf("Accepted a client connection\n");
                if (newsockfd < 0)
                        printf("ERROR on accept\n");

                bzero(buffer, 256);
                printf("About to read\n");
                n = read(newsockfd, buffer, 255);
                printf("I've red %d\n", n);
                if (n < 0)
                        printf("ERROR reading from socket\n");
                printf("Here is the message: %s\n", buffer);
                n = write(newsockfd, http_html_hdr, sizeof(http_html_hdr));
                if (n < 0)
                        printf("ERROR writing to socket\n");
                close(newsockfd);
                printf("socket closed %d\n", newsockfd);
        }
}
Now same thing on the esp32 results in being able to connect once, after that accept seems to block forever.

Code: Select all

/* Hello World Example

 This example code is in the Public Domain (or CC0 licensed, at your option.)

 Unless required by applicable law or agreed to in writing, this
 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 CONDITIONS OF ANY KIND, either express or implied.
 */
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "driver/ledc.h"
#include "lwip/err.h"
#include "lwip/sockets.h"

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t wifi_event_group;

/* The event group allows multiple bits for each event,
 but we only care about one event - are we connected
 to the AP with an IP? */
static const int CONNECTED_BIT = BIT0;

static const char *TAG = "example";


/* The examples use simple WiFi configuration that you can set via
 'make menuconfig'.

 If you'd rather not, just change the below entries to strings with
 the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
 */
#define EXAMPLE_WIFI_SSID "miau"
#define EXAMPLE_WIFI_PASS "***EDITED***"

static esp_err_t event_handler(void *ctx, system_event_t *event) {
	switch (event->event_id) {
	case SYSTEM_EVENT_STA_START:
		esp_wifi_connect();
		break;
	case SYSTEM_EVENT_STA_GOT_IP:
		xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
		break;
	case SYSTEM_EVENT_STA_DISCONNECTED:
		/* This is a workaround as ESP32 WiFi libs don't currently
		 auto-reassociate. */
		esp_wifi_connect();
		xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
		break;
	default:
		break;
	}
	return ESP_OK;
}

static void initialise_wifi(void) {
	tcpip_adapter_init();
	wifi_event_group = xEventGroupCreate();
	ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT()
	;
	ESP_ERROR_CHECK(esp_wifi_init(&cfg));
	ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
	wifi_config_t wifi_config = { .sta = { .ssid = EXAMPLE_WIFI_SSID,
			.password = EXAMPLE_WIFI_PASS, }, };
	ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
	ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
	ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
	ESP_ERROR_CHECK(esp_wifi_start());
}

const static char http_html_hdr[] =
		"HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n";
const static char http_index_html[] =
		"<html><head><title>Congrats!</title></head><body><h1>Welcome to our lwIP HTTP server!</h1><p>This is a small test page, served by httpserver-netconn.</body></html>";

static void http_server_thread() {
	xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
	false, true, portMAX_DELAY);
	int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	printf("New sock = %d\n", sock);

	struct sockaddr_in serverAddress;
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAddress.sin_port = htons(80);
	int rc = bind(sock, (struct sockaddr * ) &serverAddress,
			sizeof(serverAddress));

	printf("bind completed! %d\n", rc);

	rc = listen(sock, 10);
	printf("listen completed! %d\n", rc);


	struct sockaddr_in clientAddress;
	socklen_t clientAddressLength = sizeof(clientAddress);
	int newsockfd, n;
	char buffer[256];
	while (1) {
		printf("Waiting connection accept\n");
		newsockfd = accept(sock, (struct sockaddr * ) &clientAddress,
				&clientAddressLength);
		printf("Accepted a client connection\n");
		if (newsockfd < 0)
			printf("ERROR on accept\n");

		bzero(buffer, 256);
		printf("About to read\n");
		n = read(newsockfd, buffer, 255);
		printf("I've red %d\n", n);
		if (n < 0)
			printf("ERROR reading from socket\n");
		printf("Here is the message: %s\n", buffer);
		n = write(newsockfd, http_html_hdr, sizeof(http_html_hdr));
		if (n < 0)
			printf("ERROR writing to socket\n");
		close(newsockfd);
		printf("socket closed %d\n", newsockfd);
	}
}

void app_main() {
	nvs_flash_init();
	system_init();
	initialise_wifi();
	xTaskCreate(&http_server_thread, "http_server_netconn_thread", 2048, NULL,
			5, NULL);
}
And this is what happens:
New sock = 0
bind completed! 0
listen completed! 0
Waiting connection accept
Accepted a client connection
About to read
I've red 7
Here is the message: asdasd

socket closed 1
Waiting connection accept
ivan@ivan-desktop:~/Documents/esp/myapp$ nc 192.168.2.111 80
asdasd
HTTP/1.1 200 OK
Content-type: text/html

ivan@ivan-desktop:~/Documents/esp/myapp$ nc 192.168.2.111 80
ivan@ivan-desktop:~/Documents/esp/myapp$
EDIT: for some reason it worked another time, but I had to wait several minutes.
New sock = 0
bind completed! 0
listen completed! 0
Waiting connection accept
Accepted a client connection
About to read
I've red 7
Here is the message: asdasd

socket closed 1
Waiting connection accept
Accepted a client connection
About to read
I've red 7
Here is the message: asdasd

socket closed 2
Waiting connection accept
EDIT: And after a few more minutes It will again accept a connection:
New sock = 0
bind completed! 0
listen completed! 0
Waiting connection accept
Accepted a client connection
About to read
I've red 7
Here is the message: asdasd

socket closed 1
Waiting connection accept
Accepted a client connection
About to read
I've red 7
Here is the message: asdasd

socket closed 2
Waiting connection accept
Accepted a client connection
About to read
I've red 7
Here is the message: asdasd

socket closed 3
Waiting connection accept