-
-
Save projectgus/9e620470817d1b99422ef2cad4a155ba to your computer and use it in GitHub Desktop.
Basic TCP socket listen/accept/select demonstration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include "freertos/FreeRTOS.h" | |
#include "esp_wifi.h" | |
#include "esp_system.h" | |
#include "esp_event.h" | |
#include "esp_event_loop.h" | |
#include "nvs_flash.h" | |
#include "driver/gpio.h" | |
esp_err_t event_handler(void *ctx, system_event_t *event) | |
{ | |
return ESP_OK; | |
} | |
void app_main(void) | |
{ | |
nvs_flash_init(); | |
tcpip_adapter_init(); | |
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) ); | |
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); | |
wifi_config_t sta_config = { | |
.sta = { | |
.ssid = "my_ssid", | |
.password = "my_password", | |
.bssid_set = false | |
} | |
}; | |
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &sta_config) ); | |
ESP_ERROR_CHECK( esp_wifi_start() ); | |
ESP_ERROR_CHECK( esp_wifi_connect() ); | |
/* This is almost all a quick adaptation of Wikipedia's example: | |
https://en.wikipedia.org/wiki/Berkeley_sockets#Server | |
*/ | |
struct sockaddr_in sa; | |
int listen_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); | |
if (listen_sock == -1) { | |
perror("cannot create socket"); | |
exit(EXIT_FAILURE); | |
} | |
memset(&sa, 0, sizeof sa); | |
const int PORT = 1100; | |
sa.sin_family = AF_INET; | |
sa.sin_port = htons(PORT); | |
sa.sin_addr.s_addr = htonl(INADDR_ANY); | |
if (bind(listen_sock,(struct sockaddr *)&sa, sizeof sa) == -1) { | |
perror("bind failed"); | |
close(listen_sock); | |
return; | |
} | |
if (listen(listen_sock, 10) == -1) { | |
perror("listen failed"); | |
close(listen_sock); | |
return; | |
} | |
printf("Listening for connections on port %d\n", PORT); | |
for (;;) { | |
int conn_sock = accept(listen_sock, NULL, NULL); | |
if (conn_sock < 0) { | |
perror("accept failed"); | |
close(listen_sock); | |
exit(EXIT_FAILURE); | |
} | |
printf("Connection received. Waiting for input...\n"); | |
/* Wait for some input */ | |
struct timeval timeout = { | |
.tv_sec = 10, | |
.tv_usec = 0, | |
}; | |
fd_set rfds; | |
FD_ZERO(&rfds); | |
FD_SET(conn_sock, &rfds); | |
/* Task will block until some data is available to read | |
from conn_sock... */ | |
int r = select(conn_sock + 1, &rfds, NULL, NULL, &timeout); | |
if (r < 0) { | |
perror("select failed"); | |
return; | |
} | |
else if (r == 0) { | |
printf("Timed out with no input received.\n"); | |
} | |
else { // r > 0 | |
uint8_t buf[128] = { 0 }; | |
r = read(conn_sock, buf, sizeof(buf)-1); | |
printf("Received %d bytes: %s\n", r, buf); | |
} | |
const char *msg = "All done. Bye bye!\n"; | |
write(conn_sock, msg, strlen(msg)); | |
printf("Closing connection, waiting for another one...\n"); | |
if (shutdown(conn_sock, SHUT_RDWR) == -1) { | |
perror("shutdown failed"); | |
close(conn_sock); | |
close(listen_sock); | |
exit(EXIT_FAILURE); | |
} | |
close(conn_sock); | |
} | |
close(listen_sock); | |
printf("Done!\n"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment