listening server

kbaud1
Posts: 71
Joined: Wed Jan 17, 2018 11:55 pm

listening server

Postby kbaud1 » Mon Mar 12, 2018 6:26 pm

I bought Kolban's book and am using his code example (I added more logging after I ran into problems) for a listening server.

Code: Select all

int s, r, sock;
char recv_buf[64];
struct sockaddr_in clientAddress; struct sockaddr_in serverAddress;

Code: Select all

	
static void startServer(void)
	{

	/* Wait for the callback to set the CONNECTED_BIT in the
	   event group.
	*/
	xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
						false, true, portMAX_DELAY);


	// Create a socket that we will listen upon.
	int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock < 0)
		{
		ESP_LOGE(TAG, "socket: %d %s", sock, strerror(errno));
		goto END;
		}
	ESP_LOGE(TAG, "socket: %d %s", sock, strerror(errno));

	// Bind our server socket to a port.
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAddress.sin_port = htons(PORT);
	int rc  = bind(sock, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
	if (rc < 0)
		{
		ESP_LOGE(TAG, "bind: %d %s", rc, strerror(errno));
		goto END;
		}
	ESP_LOGE(TAG, "bind: %d %s", rc, strerror(errno));

	// Flag the socket as listening for new connections.
	rc = listen(sock, 5);
	if (rc < 0)
		{
		ESP_LOGE(TAG, "listen: %d %s", rc, strerror(errno));
		goto END;
		}

	ESP_LOGE(TAG, "listen: %d %s", rc, strerror(errno));
	ESP_LOGI(TAG, "Listening on port %s...", PORT);

	END:
		ESP_LOGI(TAG, "there was an error, skipped the rest of the port setup: %s", strerror(errno));
		// vTaskDelete(NULL);
	}

Code: Select all

static void rxtxpacket_server(void *pvParameters)
	{
	ESP_LOGI(TAG, "beginning rxtx packet server...");
	while (1)
		{
		// Listen for a new client connection.
		socklen_t clientAddressLength = sizeof(clientAddress);
		int clientSock = accept(sock, (struct sockaddr *)&clientAddress, &clientAddressLength);
		if (clientSock < 0)
			{
			ESP_LOGE(TAG, "accept: %d %s", clientSock, strerror(errno));
			goto END;
			}

		// We now have a new client ...
		int total =	10*1024;
		int sizeUsed = 0;
		char *data = malloc(total);

		ESP_LOGI(TAG, "client accepted %d...", clientSock);

		// Loop reading data.
		while(1)
			{
			ssize_t sizeRead = recv(clientSock, data + sizeUsed, total-sizeUsed, 0);
			if (sizeRead < 0)
				{
				ESP_LOGE(TAG, "recv: %d %s", sizeRead, strerror(errno));
				goto END;
				}
			if (sizeRead == 0)
				{
				break;
				}
			sizeUsed += sizeRead;
			}

		// Finished reading data.
		ESP_LOGE(TAG, "Data read (size: %d) was: %.*s", sizeUsed, sizeUsed, data);
		free(data);
		close(clientSock);
		}

	END:
		vTaskDelete(NULL);
	}

Code: Select all

void app_main()
{
    nvs_flash_init();
    initialise_wifi();
    vTaskDelay(2000 / portTICK_RATE_MS);
    if (beServer == 1)
    	{
    	ESP_LOGI(TAG, "Initializing server to listen for connections...");
    	startServer();
    	ESP_LOGI(TAG, "trying to start rxtxpacket_server...");
    	xTaskCreate(&rxtxpacket_server, "rxtxpacket_server", 2048, NULL, 5, NULL);
    	}
 
D (3740) event: SYSTEM_EVENT_STA_GOT_IP, ip:192.168.0.34, mask:255.255.255.0, gw:192.168.0.1
V (3740) event: enter default callback
I (3750) event: sta ip: 192.168.0.34, mask: 255.255.255.0, gw: 192.168.0.1
V (3750) event: exit default callback
E (3760) >: socket: 4096 Success
E (3760) >: bind: 0 Success
E (3760) >: listen: 0 Success
E (3790) >: accept: -1 Bad file number
I (5510) wifi: pm start, type:0

Thinking it might be my firewall, I tried both 7777 and port 80. used portqry.exe to see if port is open.

C:\Users\Peter>C:\PortQryV2\PortQry.exe -n 192.168.0.34

Querying target system called:

192.168.0.34

Attempting to resolve IP address to a name...


IP address resolved to espressif.domain

querying...

TCP port 80 (http service): NOT LISTENING

Any ideas what I am missing?

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

Re: listening server

Postby kolban » Mon Mar 12, 2018 6:56 pm

Howdy my friend.

Looking at the code samples your provided, it looks like you have two instances of the variable called "sock". You have one which appears global and one which appears to be local to the "startServer" function. What I'm guessing is going wrong is that in your "startServer" you are creating a socket handle, setting it to the local "sock" variable ... preparing the socket for listening and then in your "rxtxpacket_server" function using the "sock" variable which, in this case, is the global variable that has not been initialized. When you then call "accept" on it, we get a bad file number error because its value is not a valid socket handle. I suspect if you remove the local "sock" variable from "startServer" it will start to work.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

kbaud1
Posts: 71
Joined: Wed Jan 17, 2018 11:55 pm

Re: listening server

Postby kbaud1 » Mon Mar 12, 2018 8:23 pm

thank you Kolban for your rapid reply. Enjoying your book!

I replaced the following line: int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
with: sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

this cleared up the accept error but portqry says the port is not listening. Attempts to connect with various clients say the port is actively refusing a connection.

able to ping the device however.

Peter

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

Re: listening server

Postby kolban » Mon Mar 12, 2018 8:36 pm

Howdy Peter,
We might want to consider pasting the whole source to pastebin or somewhere else where we can see the whole app in context? A link can then also be supplied to this thread. Also we want to check carefully all return codes to see if any new errors have cropped up.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

kbaud1
Posts: 71
Joined: Wed Jan 17, 2018 11:55 pm

Re: listening server

Postby kbaud1 » Mon Mar 12, 2018 9:10 pm

Code: Select all

#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 "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include <stdio.h>
#include "esp_sleep.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "driver/rtc_io.h"
#include "esp32/ulp.h"
#include "ulp_main.h"
#include "driver/mcpwm.h"
#include "driver/ledc.h"
#include <errno.h>

/* 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 CONFIG_WIFI_SSID
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
#define AP_SSID "ThePartyHouse"  // for soft-AP, set variable "AP" to "1" below
#define OUT_GPIO 5				 // this is the pin toggled

/* 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? */
const int CONNECTED_BIT = BIT0;

/* Constants that aren't configurable in menuconfig */
#define PORT "7777"

#define beServer 1						// set to 1 if you want the ESP to listen for connections to PORT, otherwise it will connect to SERVER address below

#define AP 0							// set to 1 if you want SoftAP, otherwise it will connect to the AP specified in sdkconfig (menuconfig)
#if	AP
#define SERVER "192.168.4.2"			//softAP mode. this is the default IP of the first connected station (change if not the case)
#else
#define SERVER "192.168.0.52"			//station mode. this is the IP address of the echo server (usually a desktop)
#endif

// 2028 is currently max usable size that works (but is risky, since it is 4 rows over compiler limit)
#define ulp_rows 2000	// must match rows defined in assembly file

extern const uint8_t bin_start [] asm ("_binary_ulp_main_bin_start");
extern const uint8_t bin_end [] asm ("_binary_ulp_main_bin_end");

static const char *TAG = ">";
static const char *REQUEST = "message from server1";
int s, r, sock;
char recv_buf[64];
struct sockaddr_in clientAddress; struct sockaddr_in serverAddress;

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_AP_START:
    	ESP_LOGI(TAG, "Soft-AP started" );
        //esp_wifi_connect();
        break;
    case SYSTEM_EVENT_AP_STACONNECTED:
        ESP_LOGI(TAG, "station connected to this soft-AP: %s", AP_SSID );
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        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) );

    if (AP != 0)
    {
    	ESP_LOGI(TAG, "Setting WiFi mode to Soft-AP" );
    	wifi_config_t ap_config = {
    	     .ap = {
    	        .ssid = AP_SSID,
    	        .channel = 0,
    	        .authmode = WIFI_AUTH_OPEN,
    	        .ssid_hidden = 0,
    	        .max_connection = 2,
    	        .beacon_interval = 100
    	        }
    	};
    	ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_AP) );
    	ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &ap_config));
    }
    else
    {
    	ESP_LOGI(TAG, "Setting WiFi mode to station" );
		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() );
}

static void rxtxpacket_client(void *pvParameters)
{
	while (1)
	{
        if (write(s, REQUEST, strlen(REQUEST)) < 0) {
            ESP_LOGE(TAG, "... socket send failed");
            close(s);
            vTaskDelay(4000 / portTICK_RATE_MS);
            continue;
        }
        ESP_LOGI(TAG, "... socket send success");

        /* Read response */
        do {
            bzero(recv_buf, sizeof(recv_buf));
            r = read(s, recv_buf, sizeof(recv_buf)-1);
            for(int i = 0; i < r; i++) {
                putchar(recv_buf[i]);
            }
        } while(r == (sizeof(recv_buf)-1));

       ESP_LOGI(TAG, "... done reading from socket. Last read return=%d errno=%d\r\n", r, errno);
	}

}

static void rxtxpacket_server(void *pvParameters)
	{
	ESP_LOGI(TAG, "Server listening on port %s...", PORT);
	while (1)
		{
		// Listen for a new client connection.
		socklen_t clientAddressLength = sizeof(clientAddress);
		int clientSock = accept(sock, (struct sockaddr *)&clientAddress, &clientAddressLength);
		if (clientSock < 0)
			{
			ESP_LOGE(TAG, "accept: %d %s", clientSock, strerror(errno));
			goto END;
			}

		ESP_LOGE(TAG, "accept: %d %s", clientSock, strerror(errno));

		// We now have a new client ...
		int total =	10*1024;
		int sizeUsed = 0;
		char *data = malloc(total);

		ESP_LOGI(TAG, "client accepted %d...", clientSock);

		// Loop reading data.
		while(1)
			{
			ssize_t sizeRead = recv(clientSock, data + sizeUsed, total-sizeUsed, 0);
			if (sizeRead < 0)
				{
				ESP_LOGE(TAG, "recv: %d %s", sizeRead, strerror(errno));
				goto END;
				}
			if (sizeRead == 0)
				{
				break;
				}
			sizeUsed += sizeRead;
			}

		// Finished reading data.
		ESP_LOGE(TAG, "Data read (size: %d) was: %.*s", sizeUsed, sizeUsed, data);
		free(data);
		close(clientSock);
		}

	END:
		vTaskDelete(NULL);
	}

static void startClient(void)
{
    const struct addrinfo hints = {
        .ai_family = AF_INET,
        .ai_socktype = SOCK_STREAM,
    };
    struct addrinfo *res;
    struct in_addr *addr;

	/* Wait for the callback to set the CONNECTED_BIT in the
	   event group.
	*/
	xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
						false, true, portMAX_DELAY);
	if (!AP)
		{
		ESP_LOGI(TAG, "Connected to AP");
		}

	int err = getaddrinfo(SERVER, PORT, &hints, &res);	// changed PORT to "7777"

	if(err != 0 || res == NULL) {
		ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res);
		vTaskDelay(1000 / portTICK_RATE_MS);
		//continue;
	}

	/* Code to print the resolved IP.

	   Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
	addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
	ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr));

	s = socket(res->ai_family, res->ai_socktype, 0);
	if(s < 0) {
		ESP_LOGE(TAG, "... Failed to allocate socket.");
		freeaddrinfo(res);
		vTaskDelay(1000 / portTICK_RATE_MS);
		//continue;
	}
	ESP_LOGI(TAG, "... allocated socket\r\n");

	if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {
		ESP_LOGE(TAG, "... socket connect failed errno=%d. make sure echo server is listening on port 7777 and restart make monitor.", errno);
		close(s);
		freeaddrinfo(res);
		vTaskDelay(4000 / portTICK_RATE_MS);
		//continue;
	}
	else
		{
		ESP_LOGI(TAG, "... connected");
		freeaddrinfo(res);
		}
}

static void startServer(void)
	{

	/* Wait for the callback to set the CONNECTED_BIT in the
	   event group.
	*/
	xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
						false, true, portMAX_DELAY);

	ESP_LOGI(TAG, "Initializing server to listen for connections...");

	// Create a socket that we will listen upon.
	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock < 0)
		{
		ESP_LOGE(TAG, "socket: %d %s", sock, strerror(errno));
		goto END;
		}
	ESP_LOGE(TAG, "socket: %d %s", sock, strerror(errno));

	// Bind our server socket to a port.
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAddress.sin_port = htons(PORT);
	int rc  = bind(sock, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
	if (rc < 0)
		{
		ESP_LOGE(TAG, "bind: %d %s", rc, strerror(errno));
		goto END;
		}
	ESP_LOGE(TAG, "bind: %d %s", rc, strerror(errno));

	// Flag the socket as listening for new connections.
	rc = listen(sock, 5);
	if (rc < 0)
		{
		ESP_LOGE(TAG, "listen: %d %s", rc, strerror(errno));
		goto END;
		}

	ESP_LOGE(TAG, "listen: %d %s", rc, strerror(errno));

	END:
		//ESP_LOGI(TAG, "there was an error, skipped the rest of the port setup: %s", strerror(errno));
		// vTaskDelete(NULL);
		return;
	}
void toggle_pin(void *pvParameter)
{
    gpio_pad_select_gpio(OUT_GPIO);
    gpio_set_direction(OUT_GPIO, GPIO_MODE_OUTPUT);

    while(1) {
    	gpio_set_level(OUT_GPIO, 1);
    	vTaskDelay(8 / portTICK_RATE_MS);		// 9ms or less delay on either side of pin change always produces 3.3v, 64KHz square wave on scope. but 10ms drops to 50hz. why non-linear?
    	gpio_set_level(OUT_GPIO, 0);
    	vTaskDelay(8 / portTICK_RATE_MS);
    }
}

static void PWM_out (void)
{
	int i, shift = 0;

	// IO pins used for PWM outputs
	const char m_io [12] = {15, 2, 0, 4, 16, 17, 5, 18, 19, 21, 22, 23};
	const char l_io [8] = {13, 12, 14, 27, 26, 25, 33, 32};

	// configure motor PWMs
	mcpwm_config_t config = {20000, 0, 0, MCPWM_DUTY_MODE_0, MCPWM_UP_COUNTER};
	for (i = 0; i < 12; ++i)
	{
		mcpwm_gpio_init (i / 6, i % 6, m_io [i]);
		if (i & 1)
			mcpwm_init (i / 6, (i / 2) % 3, &config);
		mcpwm_set_duty_type (i / 6, (i / 2) % 3, i & 1, MCPWM_DUTY_MODE_0);
	}

	// configure LED PWMs
	ledc_channel_config_t channel = {0, LEDC_HIGH_SPEED_MODE, 0, LEDC_INTR_DISABLE, LEDC_TIMER_0, 0};
	for (i = 0; i < 8; ++i)
	{
		channel.channel = i;
		channel.gpio_num = l_io [channel.channel];
		ledc_channel_config (&channel);
	}
	ledc_timer_config_t timer = {LEDC_HIGH_SPEED_MODE, {LEDC_TIMER_10_BIT, 0}, LEDC_TIMER_0, 20000};
	ledc_timer_config (&timer);

	// Output continuously increasing, staggered duty cycle waves on all 20 channels
	while (1)
	{
		for (i = 0; i < 12; ++i)
			mcpwm_set_duty (i / 6, (i / 2) % 3, i & 1, ((shift + 52 * i) % 1024) / 10.24);

		for (i = 0; i < 8; ++i)
		{
			ledc_set_duty (LEDC_HIGH_SPEED_MODE, i, (shift + 52 * (i + 12)) % 1024);
			ledc_update_duty (LEDC_HIGH_SPEED_MODE, i);
		}

		shift = (shift + 1) % 1024;
		vTaskDelay (100 / portTICK_RATE_MS);
	}
}

void app_main()
{
    nvs_flash_init();
    initialise_wifi();
    vTaskDelay(2000 / portTICK_RATE_MS);
    if (beServer == 1)
    	{
    	startServer();
    	xTaskCreate(&rxtxpacket_server, "rxtxpacket_server", 2048, NULL, 5, NULL);
    	}
    else
    	{
    	startClient();
    	xTaskCreate(&rxtxpacket_client, "rxtxpacket_client", 2048, NULL, 5, NULL);
    	}

	//xTaskCreate (PWM_out, "PWM output", 4096, NULL, 5, NULL);
	//xTaskCreate(&toggle_pin, "toggle_pin", 512, NULL, 10, NULL);

}
D (3060) tcpip_adapter: check: local, if=0 fn=0x4011a218
0x4011a218: tcpip_adapter_dhcpc_start_api at C:/msys32/home/Peter/esp/esp-idf/components/tcpip_adapter/tcpip_adapter_l
wip.c:1065


D (3070) tcpip_adapter: dhcp client init ip/mask/gw to all-0
D (3070) tcpip_adapter: if0 start ip lost tmr: enter
D (3080) tcpip_adapter: if0 start ip lost tmr: no need start because netif=0x3ffc57b4 interval=120 ip=0
D (3090) tcpip_adapter: dhcp client start successfully
D (3090) tcpip_adapter: call api in lwip: ret=0x0, give sem
D (3100) tcpip_adapter: check: remote, if=0 fn=0x4011a218
0x4011a218: tcpip_adapter_dhcpc_start_api at C:/msys32/home/Peter/esp/esp-idf/components/tcpip_adapter/tcpip_adapter_l
wip.c:1065


V (3110) event: exit default callback
D (3750) tcpip_adapteer: if0 dhcpc cb
D (3750) tcpip_adapter: if0 ip changed=1
D (3750) event: SYSTEM_EVENT_STA_GOT_IP, ip:192.168.0.34, mask:255.255.255.0, gw:192.168.0.1
V (3750) event: enter default callback
I (3760) event: sta ip: 192.168.0.34, maask: 255.255.255.0, gw: 192.168.0.1
V (3760) event: exit default callback
I (3770) >: Initializing server to listen for connections...
E (3770) >: socket: 4096 Success
E (3780) >: bind: 0 Success
E (3780) >: listen: 0 Success
I (3780) >: Server listening on port 7777...
I (5500) wifi: pm start, type:0
Last edited by kbaud1 on Wed Mar 14, 2018 11:48 pm, edited 1 time in total.

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

Re: listening server

Postby kolban » Mon Mar 12, 2018 11:18 pm

I can't see anything obviously wrong with the program at this point. As you mentioned in a previous post, lets validate that you can make outbound network requests to 192.168.0.34:7777 from your PC and are not being thwarted by your firewall. You might also want to bump up the stack sizes on your two tasks ... at least until we determine that isn't an issue. You currently have them set to 2K. I'd also place a diagnostic log message prior to accept() to make sure that we have reached that point.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

kbaud1
Posts: 71
Joined: Wed Jan 17, 2018 11:55 pm

Re: listening server

Postby kbaud1 » Tue Mar 13, 2018 2:29 pm

Thank you again Kolban for looking at this. I have tried everything I can think of.

Bumped stack sizes to 4096.

Tried it again this time in softAP mode (bypassing my router). Same thing, "connection actively refused". Verified that windows has that port open.

I have a log message right before the accept() command (as you recommended) that prints "Server listening on port 7777" but no messages after that about accept() failing or succeeding.

It is weird. I have a log print for accept() if it errors or it succeeds and the log is silent. is something blocking?

I (412) >: Soft-AP started
I (7052) wifi: n:1 1, o:1 0, ap:1 1, sta:255 255, prof:1
I (7052) wifi: station: (redacted my mac address) join, AID=1, n, 40U
D (7052) event: SYSTEM_EVENT_AP_STACONNECTED, mac:(redacted), aid:1
I (7052) >: station connected to this soft-AP: ThePartyHouse
I (7062) >: Initializing server to listen for connections...
E (7072) >: socket: 4096 Success
E (7072) >: bind: 0 Success
E (7072) >: listen: 0 Success
I (7082) >: Serverr listening on port 7777...

kbaud1
Posts: 71
Joined: Wed Jan 17, 2018 11:55 pm

Re: listening server

Postby kbaud1 » Tue Mar 13, 2018 3:06 pm

oh, another thing, the port is fine when in client mode (station and softAP modes). It is just this listening mode that is not working.

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

Re: listening server

Postby kolban » Tue Mar 13, 2018 3:34 pm

I'd been so busy thinking about sockets and not about WiFi ... did I just hear you say that when you boot the ESP32 a TCP/IP server as a station to a remote access point, you can reach the target socket (7777) on the ESP32?

When you boot up the ESP32 as an access point, what IP address does it have?
When you boot up the ESP32 as an access point, what IP address do you try and reach it at?
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

kbaud1
Posts: 71
Joined: Wed Jan 17, 2018 11:55 pm

Re: listening server

Postby kbaud1 » Tue Mar 13, 2018 3:40 pm

when is it a softAP, the esp32 has a 192.168.4.1 address and the first connecting station is 4.2
when in station mode, the esp32 has a 192.168.0.34 address and the remote is at 0.52

here's the full code:

Code: Select all

#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 "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include <stdio.h>
#include "esp_sleep.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "driver/rtc_io.h"
#include "esp32/ulp.h"
#include "ulp_main.h"
#include "driver/mcpwm.h"
#include "driver/ledc.h"
#include <errno.h>

/* 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 CONFIG_WIFI_SSID
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
#define AP_SSID "ThePartyHouse"  // for soft-AP, set variable "AP" to "1" below
#define OUT_GPIO 5				 // this is the pin toggled

/* 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? */
const int CONNECTED_BIT = BIT0;

/* Constants that aren't configurable in menuconfig */
#define PORT "7777"

#define beServer 0						// set to 1 if you want the ESP to listen for connections to PORT, otherwise it will connect to SERVER address below

#define AP 1							// set to 1 if you want SoftAP, otherwise it will connect to the AP specified in sdkconfig (menuconfig)
#if	AP
#define SERVER "192.168.4.2"			//softAP mode. this is the default IP of the first connected station (change if not the case)
#else
#define SERVER "192.168.0.52"			//station mode. this is the IP address of the echo server (usually a desktop)
#endif

// 2028 is currently max usable size that works (but is risky, since it is 4 rows over compiler limit)
#define ulp_rows 2000	// must match rows defined in assembly file

extern const uint8_t bin_start [] asm ("_binary_ulp_main_bin_start");
extern const uint8_t bin_end [] asm ("_binary_ulp_main_bin_end");

static const char *TAG = ">";
static const char *REQUEST = "message from server1";
int s, r, sock;
char recv_buf[64];
struct sockaddr_in clientAddress; struct sockaddr_in serverAddress;

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_AP_START:
    	ESP_LOGI(TAG, "Soft-AP started" );
        //esp_wifi_connect();
        break;
    case SYSTEM_EVENT_AP_STACONNECTED:
        ESP_LOGI(TAG, "station connected to this soft-AP: %s", AP_SSID );
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        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) );

    if (AP != 0)
    {
    	ESP_LOGI(TAG, "Setting WiFi mode to Soft-AP" );
    	wifi_config_t ap_config = {
    	     .ap = {
    	        .ssid = AP_SSID,
    	        .channel = 0,
    	        .authmode = WIFI_AUTH_OPEN,
    	        .ssid_hidden = 0,
    	        .max_connection = 2,
    	        .beacon_interval = 100
    	        }
    	};
    	ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_AP) );
    	ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &ap_config));
    }
    else
    {
    	ESP_LOGI(TAG, "Setting WiFi mode to station" );
		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() );
}

static void rxtxpacket_client(void *pvParameters)
{
	while (1)
	{
        if (write(s, REQUEST, strlen(REQUEST)) < 0) {
            ESP_LOGE(TAG, "... socket send failed");
            close(s);
            vTaskDelay(4000 / portTICK_RATE_MS);
            continue;
        }
        ESP_LOGI(TAG, "... socket send success");

        /* Read response */
        do {
            bzero(recv_buf, sizeof(recv_buf));
            r = read(s, recv_buf, sizeof(recv_buf)-1);
            for(int i = 0; i < r; i++) {
                putchar(recv_buf[i]);
            }
        } while(r == (sizeof(recv_buf)-1));

       ESP_LOGI(TAG, "... done reading from socket. Last read return=%d errno=%d\r\n", r, errno);
	}

}

static void rxtxpacket_server(void *pvParameters)
	{
	ESP_LOGI(TAG, "Server listening on port %s...", PORT);

	while (1)
		{
		// Listen for a new client connection.
		socklen_t clientAddressLength = sizeof(clientAddress);
		int clientSock = accept(sock, (struct sockaddr *)&clientAddress, &clientAddressLength);
		if (clientSock < 0)
			{
			ESP_LOGE(TAG, "accept: %d %s", clientSock, strerror(errno));
			goto END;
			}

		ESP_LOGE(TAG, "accept: %d %s", clientSock, strerror(errno));

		// We now have a new client ...
		int total =	10*1024;
		int sizeUsed = 0;
		char *data = malloc(total);

		ESP_LOGI(TAG, "client accepted %d...", clientSock);

		// Loop reading data.
		while(1)
			{
			ssize_t sizeRead = recv(clientSock, data + sizeUsed, total-sizeUsed, 0);
			if (sizeRead < 0)
				{
				ESP_LOGE(TAG, "recv: %d %s", sizeRead, strerror(errno));
				goto END;
				}
			if (sizeRead == 0)
				{
				break;
				}
			sizeUsed += sizeRead;
			}

		// Finished reading data.
		ESP_LOGE(TAG, "Data read (size: %d) was: %.*s", sizeUsed, sizeUsed, data);
		free(data);
		close(clientSock);
		}

	END:
		vTaskDelete(NULL);
	}

static void startClient(void)
{
    const struct addrinfo hints = {
        .ai_family = AF_INET,
        .ai_socktype = SOCK_STREAM,
    };
    struct addrinfo *res;
    struct in_addr *addr;

	/* Wait for the callback to set the CONNECTED_BIT in the
	   event group.
	*/
	xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
						false, true, portMAX_DELAY);
	if (!AP)
		{
		ESP_LOGI(TAG, "Connected to AP");
		}

	int err = getaddrinfo(SERVER, PORT, &hints, &res);	// changed PORT to "7777"

	if(err != 0 || res == NULL) {
		ESP_LOGE(TAG, "DNS lookup failed err=%d res=%p", err, res);
		vTaskDelay(1000 / portTICK_RATE_MS);
		//continue;
	}

	/* Code to print the resolved IP.

	   Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
	addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
	ESP_LOGI(TAG, "DNS lookup succeeded. IP=%s", inet_ntoa(*addr));

	s = socket(res->ai_family, res->ai_socktype, 0);
	if(s < 0) {
		ESP_LOGE(TAG, "... Failed to allocate socket.");
		freeaddrinfo(res);
		vTaskDelay(1000 / portTICK_RATE_MS);
		//continue;
	}
	ESP_LOGI(TAG, "... allocated socket\r\n");

	if(connect(s, res->ai_addr, res->ai_addrlen) != 0) {
		ESP_LOGE(TAG, "... socket connect failed errno=%d. make sure echo server is listening on port 7777 and restart make monitor.", errno);
		close(s);
		freeaddrinfo(res);
		vTaskDelay(4000 / portTICK_RATE_MS);
		//continue;
	}
	else
		{
		ESP_LOGI(TAG, "... connected");
		freeaddrinfo(res);
		}
}

static void startServer(void)
	{

	/* Wait for the callback to set the CONNECTED_BIT in the
	   event group.
	*/
	xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
						false, true, portMAX_DELAY);

	ESP_LOGI(TAG, "Initializing server to listen for connections...");

	// Create a socket that we will listen upon.
	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock < 0)
		{
		ESP_LOGE(TAG, "socket: %d %s", sock, strerror(errno));
		goto END;
		}
	ESP_LOGE(TAG, "socket: %d %s", sock, strerror(errno));

	// Bind our server socket to a port.
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAddress.sin_port = htons(PORT);
	int rc  = bind(sock, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
	if (rc < 0)
		{
		ESP_LOGE(TAG, "bind: %d %s", rc, strerror(errno));
		goto END;
		}
	ESP_LOGE(TAG, "bind: %d %s", rc, strerror(errno));

	// Flag the socket as listening for new connections.
	rc = listen(sock, 5);
	if (rc < 0)
		{
		ESP_LOGE(TAG, "listen: %d %s", rc, strerror(errno));
		goto END;
		}

	ESP_LOGE(TAG, "listen: %d %s", rc, strerror(errno));

	END:
		//ESP_LOGI(TAG, "there was an error, skipped the rest of the port setup: %s", strerror(errno));
		// vTaskDelete(NULL);
		return;
	}
void toggle_pin(void *pvParameter)
{
    gpio_pad_select_gpio(OUT_GPIO);
    gpio_set_direction(OUT_GPIO, GPIO_MODE_OUTPUT);

    while(1) {
    	gpio_set_level(OUT_GPIO, 1);
    	vTaskDelay(8 / portTICK_RATE_MS);		// 9ms or less delay on either side of pin change always produces 3.3v, 64KHz square wave on scope. but 10ms drops to 50hz. why non-linear?
    	gpio_set_level(OUT_GPIO, 0);
    	vTaskDelay(8 / portTICK_RATE_MS);
    }
}

static void PWM_out (void)
{
	int i, shift = 0;

	// IO pins used for PWM outputs
	const char m_io [12] = {15, 2, 0, 4, 16, 17, 5, 18, 19, 21, 22, 23};
	const char l_io [8] = {13, 12, 14, 27, 26, 25, 33, 32};

	// configure motor PWMs
	mcpwm_config_t config = {20000, 0, 0, MCPWM_DUTY_MODE_0, MCPWM_UP_COUNTER};
	for (i = 0; i < 12; ++i)
	{
		mcpwm_gpio_init (i / 6, i % 6, m_io [i]);
		if (i & 1)
			mcpwm_init (i / 6, (i / 2) % 3, &config);
		mcpwm_set_duty_type (i / 6, (i / 2) % 3, i & 1, MCPWM_DUTY_MODE_0);
	}

	// configure LED PWMs
	ledc_channel_config_t channel = {0, LEDC_HIGH_SPEED_MODE, 0, LEDC_INTR_DISABLE, LEDC_TIMER_0, 0};
	for (i = 0; i < 8; ++i)
	{
		channel.channel = i;
		channel.gpio_num = l_io [channel.channel];
		ledc_channel_config (&channel);
	}
	ledc_timer_config_t timer = {LEDC_HIGH_SPEED_MODE, {LEDC_TIMER_10_BIT, 0}, LEDC_TIMER_0, 20000};
	ledc_timer_config (&timer);

	// Output continuously increasing, staggered duty cycle waves on all 20 channels
	while (1)
	{
		for (i = 0; i < 12; ++i)
			mcpwm_set_duty (i / 6, (i / 2) % 3, i & 1, ((shift + 52 * i) % 1024) / 10.24);

		for (i = 0; i < 8; ++i)
		{
			ledc_set_duty (LEDC_HIGH_SPEED_MODE, i, (shift + 52 * (i + 12)) % 1024);
			ledc_update_duty (LEDC_HIGH_SPEED_MODE, i);
		}

		shift = (shift + 1) % 1024;
		vTaskDelay (100 / portTICK_RATE_MS);
	}
}

void app_main()
{
    nvs_flash_init();
    initialise_wifi();
    vTaskDelay(2000 / portTICK_RATE_MS);
    if (beServer == 1)
    	{
    	startServer();
    	xTaskCreate(&rxtxpacket_server, "rxtxpacket_server", 4096, NULL, 5, NULL);
    	}
    else
    	{
    	startClient();
    	xTaskCreate(&rxtxpacket_client, "rxtxpacket_client", 4096, NULL, 5, NULL);
    	}

	//xTaskCreate (PWM_out, "PWM output", 4096, NULL, 5, NULL);
        //xTaskCreate(&toggle_pin, "toggle_pin", 512, NULL, 10, NULL);
}
the remote is a desktop (sometimes a laptop) usually. I run three different programs on the remote. echotool.exe, a custom c program and a custom Perl program. All 3 programs echo in either client or server mode to a specified port.
Last edited by kbaud1 on Wed Mar 14, 2018 11:49 pm, edited 1 time in total.

Who is online

Users browsing this forum: No registered users and 121 guests