Chapter 18 WebSocket Server for ESP32

Pay attention to the public account of Jiayouchuang Technology

 

Learning goals and objectives

Master the principle and working process of Websocket

Master the programming of WebSocket of Espressif ESP32

WebSocket principle

WebSocket  is a network communication protocol , a protocol provided by HTML5 for full-duplex communication on a single TCP connection.

 

Why do you need WebSockets?

Anyone who knows computer network protocols should know that the HTTP protocol is a stateless, connectionless, one-way application layer protocol. It adopts a request/response model. A communication request can only be initiated by the client, and the server responds to the request.

This communication model has a drawback: the HTTP protocol cannot enable the server to actively initiate messages to the client.

The characteristics of this one-way request are destined to be very troublesome for the client to know if the server has continuous state changes. Most web applications will implement long polling with frequent asynchronous JavaScript and XML (AJAX) requests. Polling is inefficient and wastes resources (because you have to keep connecting, or the HTTP connection is always open).

Therefore, engineers have been thinking, is there a better way. That's how WebSocket was invented. A WebSocket connection allows full-duplex communication between the client and server so that either side can push data to the other over the established connection. WebSocket only needs to establish a connection once, and it can stay connected all the time . Compared with the continuous establishment of connections in the polling method, the efficiency is obviously greatly improved.

 

 

Websocket Features

  1. Based on the TCP protocol, the server-side implementation is relatively easy.
  2. It has good compatibility with HTTP protocol. The default ports are also 80 and 443, and the HTTP protocol is used in the handshake phase, so it is not easy to shield during the handshake, and it can pass through various HTTP proxy servers.
  3. The data format is relatively lightweight, the performance overhead is small, and the communication is efficient.
  4. Text can be sent, or binary data can be sent.
  5. There is no same-origin restriction, and clients can communicate with any server.

The protocol identifier is ws (or wss if encrypted), and the server URL is the URL, as shown below.

1

2

3

4

5

6

7

8

GET /chat HTTP/1.1

Host: server.example.com

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

Origin: http://example.com

request handshake

 

1

2

3

4

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat

receive request packet

 

Note: Detailed WebSocket handshake

 

Websocket and HTTP connection process

 

Websocket working process

 

 

software design

Websocket detailed process of ESP32

 

 

 

Introduction to the Websocket interface of ESP32

  • Connection function: netconn_new();
  • Binding function: netconn_bind();
  • Listening function: netconn_listen();
  • Get the connection function: netconn_accept();
  • Receive data function: netconn_recv();
  • Send data function: netconn_write();
  • Close the connection function: netconn_close();
  • Delete connection function: netconn_delete();

For more detailed interfaces, please refer to the official guide .

 

Websocket new task writing

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

void ws_server(void *pvParameters)

{undefined

struct netconn *conn, *newconn;

//Get tcp socket connect

conn = netconn_new(NETCONN_TCP);

//bind port

netconn_bind(conn, NULL, WS_PORT);

//monitor

netconn_listen(conn);

//Wait for client to connect

while (netconn_accept(conn, &newconn) == ERR_OK)

{undefined

//New connection: waiting for connection, connection process, data read

ws_server_netconn_serve(newconn);

}

//Close websocket server connect

netconn_close(conn);

netconn_delete(conn);

}

 

Websocket connection process code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

static void ws_server_netconn_serve(struct netconn *conn) {undefined

//Apply for SHA1

p_SHA1_Inp = pvPortMallocCaps(WS_CLIENT_KEY_L + sizeof(WS_sec_conKey),

MALLOC_CAP_8BIT);

//Apply for SHA1 result

p_SHA1_result = pvPortMallocCaps(SHA1_RES_L, MALLOC_CAP_8BIT);

//Check if malloc suceeded

if ((p_SHA1_Inp != NULL) && (p_SHA1_result != NULL)) {undefined

//Receive data from the "connect" process

if (netconn_recv(conn, &inbuf) == ERR_OK) {undefined

//Read the data of the "connect" process to buf

netbuf_data(inbuf, (void**) &buf, &i);

//Pass the server's key to SHA1

for (i = 0; i < sizeof(WS_sec_conKey); i++)

{undefined

// put in the last 24 bytes

p_SHA1_Inp[i + WS_CLIENT_KEY_L] = WS_sec_conKey[i];

}

//Search the client's key

p_buf = strstr(buf, WS_sec_WS_keys);

//find key

if (p_buf != NULL) {undefined

//get Client Key

for (i = 0; i < WS_CLIENT_KEY_L; i++)

{undefined

// put in the first 24 bytes

p_SHA1_Inp[i] = *(p_buf + sizeof(WS_sec_WS_keys) + i);

}

// Calculate hash

esp_sha(SHA1, (unsigned char*) p_SHA1_Inp, strlen(p_SHA1_Inp),

(unsigned char*) p_SHA1_result);

//Turn to base64

p_buf = (char*) _base64_encode((unsigned char*) p_SHA1_result,

SHA1_RES_L, (size_t*) &i);

//free SHA1 input

free(p_SHA1_Inp);

//free SHA1 result

free(p_SHA1_result);

if (p_payload != NULL) {undefined

// prepare the "handshake" frame

sprintf(p_payload, WS_srv_hs, i - 1, p_buf);

//Send the "handshake" frame

netconn_write(conn, p_payload, strlen(p_payload),NETCONN_COPY);

//free base64

free(p_buf);

//free "handshake" memory

free(p_payload);

//websocket connection is successful

WS_conn = conn;

//"Receive data"

while (netconn_recv(conn, &inbuf) == ERR_OK) {undefined

. . . . . .

 

Websocket send code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

err_t WS_write_data(char* p_data, size_t length) {undefined

//websocket is not connected, exit directly

if (WS_conn == NULL)

return ERR_CONN;

//Data frame length overflow, exit directly

if (length > WS_STD_LEN)

return ERR_VAL;

err_t result;

// header

WS_frame_header_t hdr;

hdr.FIN = 0x1;

hdr.payload_length = length;

hdr.mask = 0;

hdr.reserved = 0;

hdr.opcode = WS_OP_TXT;

// send header

result = netconn_write(WS_conn, &hdr, sizeof(WS_frame_header_t), NETCONN_COPY);

if (result != ERR_OK)

return result;

//send data

return netconn_write(WS_conn, p_data, length, NETCONN_COPY);

}

The code has all Chinese comments

 

Test process and effect display

test process

  1. Change the STA account password
  2. WebSocket Testing Using Computer Assistant Tool

Show results

connect

send

control lights

 

Disconnect

 

WebSocketSummary

  • This source code is mainly to learn the whole process of WebSocket. In fact, there are still many places that can be improved. After understanding WebSocket, you can fly to the sky by yourself.
  • Source address: https://github.com/xiaolongba/wireless-tech

 

Click me -> more ESP32 development guide series catalog

Tags: Chapter 18 WebSocket Server for ESP32

ESP32 development ESP32 Development Guide ESP32

Related: Chapter 18 WebSocket Server for ESP32