ESP8266创建一个 TCP 服务器
在 ESP8266 RTOS SDK 中,创建一个 TCP 服务器需要以下步骤:
-
初始化 Wi-Fi:在STA模式下连接到 Wi-Fi,或者设置为 AP 模式。这里我们会设置为 AP 模式。
-
创建一个 socket:使用
socket()
函数创建一个新的 socket。 -
绑定 socket:使用
bind()
函数将新创建的 socket 绑定到一个 IP 地址和端口上。 -
监听连接:使用
listen()
函数开始监听新的客户端连接。 -
接受连接:使用
accept()
函数接受新的客户端连接。 -
处理连接:在连接被接受后,可以使用
read()
和write()
函数来读取和发送数据。
现在,我们来详细解释一下如何在 ESP8266 RTOS SDK 中做这些事情。
首先,让我们设置 ESP8266 为 AP 模式,并创建一个名为 “ChinaIOT--XXXX” 的 SSID,不用密码。
c
复制
#include “esp_wifi.h”
#define WIFI_SSID “ChinaIOT--XXXX”
void wifi_init_softap(void)
{
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
wifi_config_t wifi_config = {
.ap = {
.ssid = WIFI_SSID,
.ssid_len = strlen(WIFI_SSID),
.channel = 1,
.password = "",
.authmode = WIFI_AUTH_OPEN,
.ssid_hidden = ,
.max_connection = 4,
.beacon_interval = 100,
},
};
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() );
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s",
WIFI_SSID, "");
}
接下来,我们创建一个 TCP 服务器。
c
复制
#include “lwip/err.h”
#include “lwip/sockets.h”
#include <string.h>
#define SERVER_PORT 80
void tcp_server_task(void *pvParameters)
{
char rx_buffer[128];
char addr_str[128];
int addr_family;
int ip_protocol;
struct sockaddr_in dest_addr;
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(SERVER_PORT);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
inet_ntoa_r(dest_addr.sin_addr, addr_str, sizeof(addr_str) - 1);
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (listen_sock < ) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
vTaskDelete(NULL);
return;
}
int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err != ) {
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
vTaskDelete(NULL);
return;
}
err = listen(listen_sock, 1);
if (err != ) {
ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
vTaskDelete(NULL);
return;
}
while (1) {
ESP_LOGI(TAG, "Socket listening");
struct sockaddr_in source_addr;
uint addr_len = sizeof(source_addr);
int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
if (sock < ) {
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
break;
}
// Convert ip address to string
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
while (1) {
int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, );
if (len < ) {
ESP_LOGE(TAG, "recv failed: errno %d", errno);
break;
} else if (len == ) {
ESP_LOGI(TAG, "Connection closed");
break;
} else {
rx_buffer[len] = ; // Null-terminate whatever we received and treat it like a string
ESP_LOGI(TAG, "Received %d bytes从 '%s'", len, rx_buffer);
// Echo received data back
int err = send(sock, rx_buffer, len, );
if (err < ) {
ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
break;
}
}
}
if (sock != -1) {
ESP_LOGE(TAG, "Shutting down socket and restarting...");
shutdown(sock, );
close(sock);
}
}
}
现在,我们有一个简单的 TCP 服务器,它会接收连接,读取数据,然后将接收到的数据发送回去。
如果你想关闭 STA 模式和 TCP 连接,并切换到 AP 模式,你可以先关闭 TCP 服务器的 socket,并调用 esp_wifi_set_mode(WIFI_MODE_AP)
来切换到 AP 模式。
如果你尝试关闭一个没有打开的 socket(比如,你没有调用 socket()
或者已经调用了 close()
的 socket),close()
函数将返回 -1,并设置 errno 为 EBADF(无效的文件描述符)。
在你的 Wi-Fi 配置中,ssid_hidden
是一个布尔值,决定了你的 SSID 是否被广播。如果 ssid_hidden
是 0,那么你的 SSID 将会被广播,并且可以在无线网络列表中看到。如果 ssid_hidden
是 1,那么你的 SSID 将不会被广播,你需要手动输入 SSID 才能连接到这个网络。
这个配置中的其他参数有:
.ssid
是你的 SSID,也就是你的网络的名称。.ssid_len
是你的 SSID 的长度。.channel
是你的 Wi-Fi 网络使用的无线信道。.password
是你的 Wi-Fi 网络的密码。在这个例子中,我们将它设置为 “”,也就是没有密码。.authmode
是你的 Wi-Fi 网络的认证模式,在这个例子中,我们使用的是 WIFI_AUTH_OPEN,也就是说我们的网络是开放的,没有密码保护。.max_connection
是你的 Wi-Fi 网络允许的最大连接数。.beacon_interval
是你的 Wi-Fi 网络的信标间隔,单位是毫秒。