Socket Server

dcm684
Posts: 2
Joined: Tue Apr 11, 2017 8:21 pm

Socket Server

Postby dcm684 » Tue Apr 11, 2017 8:37 pm

I am trying to create a socket with a client that I can leave open indefinitely where both the server and client can send messages at anytime without have to reopen the socket. The server on the ESP32 can receive one message before being unable to receive any more messages without closing and reopening the client socket.

After enabling some of the debugging options in lwipopts.h, I see that the first time its called there is a buffer where the received message is stored, but after recv is called the netbuff is deleted.

Prior to reading I get the following when I call recv()

Code: Select all

lwip_recvfrom: netconn_recv err=0, netbuf=0x3ffc8f40
lwip_recvfrom: buflen=1 len=1024 off=0 sock->lastoffset=0
After the read I get:

Code: Select all

lwip_recvfrom: netconn_recv err=-13, netbuf=0x0
lwip_recvfrom(1): buf == NULL, error is "Connection aborted."!
The following code is an an event if that matters. Thanks for any help.

Code: Select all

void socket_main(void *pvParameter)
{
	// Create the actual socket
	int mainSocket = socket_create(SOCKET_PORT);

	if (mainSocket >= 0) {

		int option = true;
		if (setsockopt(mainSocket, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof(option)) < 0) {
			ESP_LOGE(LOG_TAG, "Failed to keep alive. %s", strerror(errno));
		}

		// As long as a valid client socket is available keep reading
		for (;;) {

			int clientSocket = socket_wait_for_client(mainSocket);
			if (clientSocket < 0) {
				break;
			}

			while(socket_connection_handler(clientSocket)){}

			closesocket(clientSocket);
		}

		closesocket(mainSocket);
	}
	vTaskDelete(NULL);
}

Code: Select all

int socket_create(uint16_t portNumber)
{
	struct sockaddr_in serverAddress;

	// Create the socket
	int theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	if (theSocket < 0) {
		ESP_LOGE(LOG_TAG, "Failed to create socket. Error: %s", strerror(errno));
		return theSocket;
	}

	// Bind the socket to the port
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAddress.sin_port = htons(portNumber);

	int result = bind(theSocket,
			(struct sockaddr *) &serverAddress,
			sizeof(serverAddress));

	if (result < 0) {
		ESP_LOGE(LOG_TAG, "Failed to bind socket. Error: %s", strerror(errno));
			closesocket(theSocket);
			return result;
	}

	// Indicate that the socket is look for new connections
	result = listen(theSocket, SOCKET_BACKLOG);

	if (result < 0) {
		ESP_LOGE(LOG_TAG, "Failed to listen on socket. Error: %s", strerror(errno));
			closesocket(theSocket);
			return result;
	}

	return theSocket;
}

Code: Select all

int socket_wait_for_client(int hostSocket)
{
	struct sockaddr_in clientAddress;

	socklen_t clientAddrLen = sizeof(clientAddress);

	int clientSocket = accept(hostSocket, (struct sockaddr *) &clientAddress, &clientAddrLen);

	if (clientSocket < 0) {
		ESP_LOGE(LOG_TAG, "Failed to connect to client. Error: %s",strerror(errno));

		return clientSocket;
	}
	return clientSocket;
}

bool socket_connection_handler(int clientSocket)
{
	int maxRead = 1024;
	char *readData = malloc(maxRead);
	bool retVal = false;
	ssize_t bytesJustRead;

	for (;;) {
		// Wait while nothing has been received
		do {
			// Send whatever is in the outbound, UART to WiFi buffer
			check_and_process_out_queue(clientSocket);

			// Peek to see what's in the RX buffer
			bytesJustRead = recv(clientSocket, readData, maxRead,MSG_PEEK);

			// Only delay on an empty RX buffer
			if (bytesJustRead == 0) {
				vTaskDelay(25 / portTICK_PERIOD_MS);
			}
		} while (bytesJustRead == 0);

		// Actually read this time. If a negative result occurs,
		// it will be handled here
		bytesJustRead = recv(clientSocket, readData, maxRead, MSG_DONTWAIT);

		// Handle errors
		if (bytesJustRead < 0) {
			ESP_LOGE(LOG_TAG, "Read failed (%i). %s", bytesJustRead,	strerror(errno));

		} else if (bytesJustRead > 0) {
			// Log the read data.
			ESP_LOGI(LOG_TAG, "Data read (%i): %.*s", bytesJustRead, bytesJustRead, readData);

			retVal = true;
		}
	}

	free(readData);

	return retVal;
}


dcm684
Posts: 2
Joined: Tue Apr 11, 2017 8:21 pm

Re: Socket Server

Postby dcm684 » Wed Apr 12, 2017 4:31 pm

Turn out that it was an issue with the client device, not the ESP32 server. The client would try to send something and if it did not receive a response it closed the socket. I added some code to the socket handler that will diagnose if the client closed the socket.

To help anyone else in the future, I've included that function below.

Code: Select all

bool socket_connection_handler(int clientSocket)
{
	int maxRead = 1024;
	char *readData = malloc(maxRead);
	bool retVal = false;
	ssize_t bytesJustRead;

	for (;;) {
		do {
			// Reset errno
			errno = ERR_OK;
			
			// Peek to see what's in the RX buffer
			bytesJustRead = recv(clientSocket,
					readData,
					maxRead,
					MSG_PEEK);

			// Only delay on an empty RX buffer
			if (bytesJustRead == 0) {
				vTaskDelay(25 / portTICK_PERIOD_MS);
			}
		} while ((bytesJustRead == 0) && (errno == ERR_OK));

		if ((bytesJustRead <= 0) && (errno != ERR_OK)) {
			ESP_LOGI(LOG_TAG, "Exiting %s due to error \"%s\"",
					__FUNCTION__,
					strerror(errno));
			break;
		}

		// Actually read this time. If a negative result occurs,
		// it will be handled here
		bytesJustRead = recv(clientSocket,
				readData,
				maxRead,
				MSG_DONTWAIT);

		// Handle errors
		if (bytesJustRead < 0) {
			ESP_LOGE(LOG_TAG, "Read failed (%i). %s",
					bytesJustRead,
					strerror(errno));

		} else if (bytesJustRead > 0) {
			// Log the read data.
			ESP_LOGI(LOG_TAG, "Data read (%i): %.*s",
					bytesJustRead,
					bytesJustRead,
					readData);

			retVal = true;
		}
	}

	free(readData);
	return retVal;

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

Re: Socket Server

Postby kolban » Thu Apr 13, 2017 3:10 am

Is it possible the client is closing the connection?
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

Who is online

Users browsing this forum: ok-home and 250 guests