tags: ESP8266
Special attention:
(1). The attribute of .fd may not perform NO_BLOCK configuration
(2). Struct TimeVal TV; TV.tv_usec Can't be less than 1000, otherwise the system crashes will collapse this unit is US
/* BSD Socket API 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 <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_event.h"
#include "protocol_examples_common.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include "xzh_wifi.h"
#define PORT 10000
static const char *TAG = "example";
static void tcp_server_task(void *pvParameters)
{
char rx_buffer[128];
char addr_str[128];
int addr_family;
int ip_protocol;
while (1) {
#ifdef CONFIG_EXAMPLE_IPV4
struct sockaddr_in destAddr;
destAddr.sin_addr.s_addr = htonl(INADDR_ANY);
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(PORT);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);
#else // IPV6
struct sockaddr_in6 destAddr;
bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un));
destAddr.sin6_family = AF_INET6;
destAddr.sin6_port = htons(PORT);
addr_family = AF_INET6;
ip_protocol = IPPROTO_IPV6;
inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
#endif
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (listen_sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket created");
int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket binded");
err = listen(listen_sock, 1);
if (err != 0) {
ESP_LOGE(TAG, "Error occured during listen: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket listening");
#if 0
for(;;)
{
#ifdef CONFIG_EXAMPLE_IPV6
struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6
#else
struct sockaddr_in sourceAddr;
#endif
uint addrLen = sizeof(sourceAddr);
int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket accepted");
while (1) {
int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
// Error occured during receiving
if (len < 0) {
ESP_LOGE(TAG, "recv failed: errno %d", errno);
break;
}
// Connection closed
else if (len == 0) {
ESP_LOGI(TAG, "Connection closed");
break;
}
// Data received
else {
#ifdef CONFIG_EXAMPLE_IPV6
// Get the sender's ip address as string
if (sourceAddr.sin6_family == PF_INET) {
inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
} else if (sourceAddr.sin6_family == PF_INET6) {
inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
}
#else
inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
#endif
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
ESP_LOGI(TAG, "%s", rx_buffer);
int err = send(sock, rx_buffer, len, 0);
if (err < 0) {
ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
break;
}
}
}
if (sock != -1) {
ESP_LOGE(TAG, "Shutting down socket and restarting...");
shutdown(sock, 0);
close(sock);
//close(listen_sock);
//vTaskDelay(500/portTICK_PERIOD_MS);
}
}
#else
fd_set readfds, testfds;
int client_sockfd;
uint client_len;
struct sockaddr_in sourceAddr;
int result;
FD_ZERO(&readfds);
FD_SET(listen_sock, &readfds);// Add the server side Socket to the collection
while(1)
{
char ch;
int fd;
int nread;
testfds = readfds;// In the descriptor set COPY to the SELECT query query, SELECT will modify it, so be sure to use variables separately.
//printf("server waiting\n");
/ * Unlink blocking, and test file descriptor change * /
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 10*1000; // 10MS Can't be less than 1000, otherwise the system will collapse
result = select(FD_SETSIZE, &testfds, (fd_set *)0,(fd_set *)0, (struct timeval *) &tv); // fd_setsize: System default maximum file descriptor
// Result = SELECT (FD_SETSIZE, & TESTFDS, (fd_set *) 0, (FD_SET *) 0, (Struct Timeval *) & 0); // If TV is 0 completely blocked
if(result < 1)
{
//perror("server5");
//exit(1);
}
/ * Scan all file descriptors * /
for(fd = 0; fd < FD_SETSIZE; fd++)
{
/ * Find related file descriptor * /
if(FD_ISSET(fd,&testfds))
{
/ * Determine if it is a server socket, which is represented as a client request connection. * /
if(fd == listen_sock)
{
client_len = sizeof(sourceAddr);
client_sockfd = accept(listen_sock,
(struct sockaddr *)&sourceAddr, &client_len);
FD_SET(client_sockfd, &readfds);// Add the client socket to the collection
printf("adding client on fd %d\n", client_sockfd);
}
/ * When there is a data request in the client socket * /
else
{
#if 0
ioctl(fd, FIONREAD, &nread);// obtain the amount of data to NREAD
/ * The customer data request is complete, close the socket, clear the corresponding descriptor from the collection * /
if(nread == 0)
{
//close(fd);
// fd_clr (fd, & readfds); // Remove the close FD
//printf("removing client on fd %d\n", fd);
}
/ * Handle customer data request * /
else
{
read(fd, &ch, 1);
//sleep(5);
printf("serving client on fd %d\n", fd);
ch++;
write(fd, &ch, 1);
}
#else
char rx_buffer[128];
int len = recv(fd, rx_buffer, sizeof(rx_buffer) - 1, 0);
if (len < 0)
{
ESP_LOGE(TAG, "recv failed: errno %d", errno);
//break;
}
// Connection closed
else if (len == 0)
{
ESP_LOGI(TAG, "Connection closed");
close(fd);
FD_CLR(fd, &readfds); / / Remove the close FD
printf("serving client on fd %d\n", fd);
//break;
}
else
{
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
//ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
ESP_LOGI(TAG, "%s", rx_buffer);
}
#endif
}
}
}
}
#endif
}
vTaskDelete(NULL);
}
void app_main()
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
//ESP_ERROR_CHECK(example_connect());
xzh_wifi_ap_init("XZH_ESP8266","xuanzihao");
xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL);
}
About the AP mode, note that XeventGroupWaitBits in xzh_wifi_ap_init is used to block, wait for AP to build (WiFi_Event_ap_start event occurs)
// AP section
static void ip_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
switch (event_id) {
case IP_EVENT_AP_STAIPASSIGNED:
//xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
ESP_LOGI(TAG, "IP_EVENT_AP_STAIPASSIGNED\r\n \r\n");
break;
default:
break;
}
return;
}
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
switch (event_id) {
case WIFI_EVENT_AP_STACONNECTED:
{
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
MAC2STR(event->mac), event->aid);
break;
}
case WIFI_EVENT_AP_STADISCONNECTED:
{
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
MAC2STR(event->mac), event->aid);
break;
}
case WIFI_EVENT_AP_START:
{
ESP_LOGI(TAG, "WIFI_EVENT_AP_START\r\n \r\n");
xEventGroupSetBits(s_connect_event_group, GOT_IPV4_BIT);
break;
}
default:
break;
}
return;
}
esp_err_t xzh_set_ap_info(const char *ssid, const char *passwd)
{
strncpy(s_connection_name, ssid, sizeof(s_connection_name));
strncpy(s_connection_passwd, passwd, sizeof(s_connection_passwd));
wifi_config_t wifi_config = { 0 };
strncpy((char *)&wifi_config.ap.ssid, s_connection_name, 32);
strncpy((char *)&wifi_config.ap.password, s_connection_passwd, 64);
wifi_config.ap.authmode = WIFI_AUTH_WPA2_PSK;
// ESP_LOGI(TAG, "Connecting to %s...", wifi_config.sta.ssid);
// ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
return ESP_OK;
}
esp_err_t xzh_wifi_ap_init(const char *ssid, const char *passwd)
{
if (s_connect_event_group != NULL) {
return ESP_ERR_INVALID_STATE;
}
s_connect_event_group = xEventGroupCreate();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
//ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &on_wifi_disconnect, NULL));
//ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &on_got_ip, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
wifi_config_t wifi_config = { 0 };
strncpy((char *)&wifi_config.ap.ssid, ssid, 32);
strncpy((char *)&wifi_config.ap.password, passwd, 64);
wifi_config.ap.authmode = WIFI_AUTH_WPA2_PSK;
wifi_config.ap.max_connection = 2;
ESP_LOGI(TAG, "SSID:%s PASS:%s", wifi_config.ap.ssid,wifi_config.ap.password);
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
xEventGroupWaitBits(s_connect_event_group, CONNECTED_BITS, true, true, portMAX_DELAY);
return ESP_OK;
}
Because what the embedded course does, I want to use esp8266 to send the image obtained by the camera on the development board to the computer. So I learned a bit by referring to the example on the pu...
need: ESP32 check AP mode Other equipment Connect an ESP32 AP ESP32 connection TCP Server ESP32 is transmitted to TCP Server as TCP Client Test instruction: Test steps: 1 Android mobile phone can use ...
1.stm32 Drive the ESP8266 module The ESP8266 module used by the author is a module developed by the point atomic, which turns the communication interface into a serial port. The introduction of the ES...
One year ago, I would like to make a simple smart home product yourself on ESP8266, and then facing the internship and graduation work, I went to Zigbee. I have been to the releare, I think about this...
Today we are doing an instance of ESP8266 to open hotspot mode! ! If there is a problem with the program debugging, please leave a message! !...
AP/STA mode of ESP8266 AP: The wireless access point is the creator of a wireless network and the central node of the network. Generally, a wireless router used in a home or office is an AP. STA: Each...
ESP8266 AP mode ESP8266 has three working modes, namely wireless access point mode (AP), wireless terminal mode (STA mode) and hybrid mode (a combination of the above two modes). This section introduc...
AP Mode content os_memset Code head File Macro Global variable Initialize WiFi function [ESP8266_AP_INIT] Software timing callback function [os_timer_1_cb] user_init Overall code Summary frame content...
AP Establishing WIFI, STA accepts the connection, mutual transfer serial data and TCP STA Connection WIFI, connected AP, the serial data to each other Test Example transmitting abc / s...
First import the espconn.h file. The use of this file also needs to add #include "ip_addr.h" inside the header file, otherwise the espconn header file will report an error that the ip_addr t...