explain
1. Reference code
https://www.cnblogs.com/orlion/p/6119812.html
#include <string.h> #include <stdio.h> #include <stdlib.h> #include <netinet/in.h> #include <arpa/inet.h> #include <ctype.h> #include "wrap.h" #define MAXLINE 80 #define SERV_PORT 8001 int main(int argc, char **argv) { int i, maxi, maxfd, listenfd, connfd, sockfd; int nready, client[FD_SETSIZE]; ssize_t n; fd_set rset, allset; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; socklen_t cliaddr_len; struct sockaddr_in cliaddr, servaddr; listenfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); Listen(listenfd, 20); maxfd = listenfd; maxi = -1; for (i = 0; i < FD_SETSIZE; i++) client[i] = -1; /* -1 indicates available entry */ FD_ZERO(&allset); FD_SET(listenfd, &allset); for ( ; ; ) { rset = allset; /* structure assignment */ nready = select(maxfd+1, &rset, NULL, NULL, NULL); if (nready < 0) perr_exit("select error"); if (FD_ISSET(listenfd, &rset)) { /* new client connection */ cliaddr_len = sizeof(cliaddr); connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port)); for (i = 0; i < FD_SETSIZE; i++) if (client[i] < 0) { client[i] = connfd; /* save descriptor */ break; } if (i == FD_SETSIZE) { fputs("too many clients\n", stderr); exit(1); } FD_SET(connfd, &allset); /* add new descriptor to set */ if (connfd > maxfd) maxfd = connfd; /* for select */ if (i > maxi) maxi = i; /* max index in client[] array */ if (--nready == 0) continue; /* no more readable descriptors */ } for (i = 0; i <= maxi; i++) { /* check all clients 714 for data */ if ( (sockfd = client[i]) < 0) continue; if (FD_ISSET(sockfd, &rset)) { if ( (n = Read(sockfd, buf, MAXLINE)) == 0) { Close(sockfd); FD_CLR(sockfd, &allset); client[i] = -1; } else { int j; for (j = 0; j < n; j++) buf[j] = toupper(buf[j]); Write(sockfd, buf, n); } if (--nready == 0) break; /* no more readable descriptors */ } } } }
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> void perr_exit(const char *s) { perror(s); exit(1); } int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr) { int n; again: if ((n = accept(fd, sa, salenptr)) < 0) { if ((errno == ECONNABORTED) || (errno == EINTR)) goto again; else perr_exit("accept error"); } return n; } void Bind(int fd, struct sockaddr *sa, socklen_t salen) { if (bind(fd, sa, salen) < 0) perr_exit("bind error"); } void Connect(int fd, const struct sockaddr *sa, socklen_t salen) { if (connect(fd, sa, salen) < 0) perr_exit("connent error"); } void Listen(int fd, int backlog) { if (listen(fd, backlog) < 0) perr_exit("listen error"); } int Socket(int family, int type, int protocol) { int n; if ((n = socket(family, type, protocol)) < 0) perr_exit("socket error"); return n; } ssize_t Read(int fd, void *ptr, size_t nbytes) { ssize_t n; again: if ((n = read(fd, ptr, nbytes)) < 0) { if (errno == EINTR) goto again; else return -1; } return n; } ssize_t Write(int fd, const void *ptr, size_t nbytes) { ssize_t n; again: if ((n = write(fd, ptr, nbytes)) == -1) { if (errno == EINTR) goto again; else return -1; } return n; } void Close(int fd) { if (close(fd) == -1) perr_exit("close error"); } ssize_t Readn(int fd, void *vptr, size_t n) { size_t nleft; ssize_t nread; char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ((nread = read(fd, ptr, nleft)) < 0) { if (errno == EINTR) nread = 0; else return -1; } else if (nread == 0) { break; } nleft -= nread; ptr += nread; } return n - nleft; } ssize_t Writen(int fd, const void *vptr, size_t n) { size_t nleft; ssize_t nwritten; const char *ptr; ptr = vptr; nleft = n; while (nleft > 0) { if ((nwritten = write(fd, ptr, nleft)) <= 0) { if (nwritten < 0 && errno == EINTR) nwritten = 0; else return -1; } nleft -= nwritten; ptr += nwritten; } return n; } static ssize_t my_read(int fd, char *ptr) { static int read_cnt; static char *read_ptr; static char read_buf[100]; if (read_cnt <= 0) { again: if ((read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) { if (errno == EINTR) goto again; return -1; } else if (read_cnt == 0) return 0; read_ptr = read_buf; } read_cnt--; *ptr = *read_ptr++; return 1; } ssize_t Readline(int fd, void *vptr, size_t maxlen) { ssize_t n, rc; char c, *ptr; ptr = vptr; for (n = 1; n < maxlen; n++) { if ((rc = my_read(fd, &c)) == 1) { *ptr++ = c; if (c == '\n') break; } else if (rc == 0) { *ptr = 0; return n - 1; } else { return -1; } } *ptr = 0; return n; }
2. Description
Because the current project needs to achieve high-speed and efficient transmission, a set of TCP server program is encapsulated by lwip's select
It is also recommended that big guys use this program as a TCP server. In this way, they can use this bottom layer for similar projects in the future
Download program to development board
1. Put the code of this section in the English directory

2. Right click and select open with VScode

3. About partial configuration
The user can configure the module hotspot name and the router information connected to the module in this function file

If you don't need to connect the router or modify it, you can't connect internally at most

The user can set the port number of the TCP server listening here: 8888 is listening now

4. Compile and download to the development board (the first compilation takes a long time)

test
1. After the program is downloaded, there will be a program named ESP32_WIFI hotspots

2. If the module is connected to the router, the log will also print the information after connecting to the router

3. Prompt
If the big guy uses the hotspot of the mobile phone or computer connection module to test,
Then the IP address of the TCP server of the module is 192.168 4.1 port number: 8888
Now my computer and module are in a router. Ha, I use 192.168 0.102 address test
4. Open the network debugging assistant test
What is written in the program is to return whatever data is received

Add another client

Program instructions (how to use it first)
1. If users need to migrate, they can directly put the following files into their own project

2. Create a TCP server (see the following figure for each parameter)


3. The data received by the server is in this function (this function is in the TCP listening task. Be careful not to block it in this function)

4. About sending data to the client
1. There are two TCP functions for sending data to the client_ server_ select_ Write and tcp_server_select_send

2, tcp_server_select_write means that it can only be called in the received data
3. Suppose you need to send the data received from the serial port to all TCP clients_ server_ select_ Send (- 1, data address, data length)

4. Suppose you need to send the data received from the serial port to the specified TCP client, you need to get the client's index in the receiving function first
I'm just giving an example. Generally, after receiving what data, I assign the value to which client the following data is sent


Program description
1. Create a TCP server


2. The TCP server monitors the connection and receives data





3. Send data
Ringbuffer + semaphore + task is used to send data

When sending data, the number is stored in Ringbuffer and the semaphore is + 1

Get the semaphore in the task, then get the data in the cache, and then send the data to the client
