Receive data from TCP (FreeRTOS, LWIP) - tcp

When I start this program (see below), all is working fine. But when I disable return data back to TPCIP, program working bad.
Here is program, working fine: [1]: http://s27.postimg.org/seixg63hf/problem_2.jpg
static err_t prijata_data(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
void *data;
if (err == ERR_OK && p != NULL) {
// information of receive data
tcp_recved(pcb, p->tot_len);
//free buffer
pbuf_free(p);
data = p->payload; //copy value to send out of queue
xQueueSend(queue_ethernet, &data, 10); //send value to queue
//send data out
err = tcp_write(pcb, p->payload, p->len, TCP_WRITE_FLAG_COPY);
tcp_sent(pcb, NULL); // No need to call back
}
else
{
pbuf_free(p);
}
if (err == ERR_OK && p == NULL) {
close_conn(pcb);
}
return ERR_OK;
}
And this function going here:
s
static err_t prijimani_dat(void *arg, struct tcp_pcb *pcb, err_t err){
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(err);
tcp_setprio(pcb, TCP_PRIO_MIN);
tcp_recv(pcb, prijata_data);
tcp_err(pcb, server_err);
tcp_poll(pcb, server_poll, 4);
return ERR_OK;
}
Complet communication is implement in task FreeRTOS:
extern void TCP_connection(void *pvParameters)
{
UNUSED(pvParameters);
const portTickType xDelayTime = 5 / portTICK_RATE_MS;
struct tcp_pcb *tcp_server;
tcp_server = tcp_new();
tcp_bind(tcp_server, IP_ADDR_ANY, TCP_PORT);
while (1){
tcp_server = tcp_listen(tcp_server);
tcp_accept(tcp_server, prijimani_dat);
vTaskDelay(xDelayTime);
}
}
But when I can only reading from TCP, and I do not want back data to TCPIP, program working bad.: [2]: http://s21.postimg.org/wlhqh31g5/problem_1.jpg
static err_t prijata_data(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err){
void *data;
if (err == ERR_OK && p != NULL) {
/* information of receive data */
tcp_recved(pcb, p->tot_len);
//free buffer
pbuf_free(p);
data = p->payload; /*copy value to send out of queue*/
xQueueSend(queue_ethernet, &data, 10); //send value to queue
}
else
{
pbuf_free(p);
}
if (err == ERR_OK && p == NULL) {
close_conn(pcb);
}
return ERR_OK;
}

There is a very old example of how to use FreeRTOS with lwIP in the FreeRTOS Interactive site. Although a lot of the code included in this example has now been superseded the integration with lwIP should still be valid and make a reference for you.
If you are using one of the processors listed on the FreeRTOS+TCP examples page (FreeRTOS+TCP being FreeRTOS's own TCP/IP stack) then that may provide a further reference.

I´m trying all.
There is any mistake, but what? When I try ping, all is done correctly.
C:\>ping 192.168.0.145 -n 10
Pinging 192.168.0.145 with 32 bytes of data:
Reply from 192.168.0.145: bytes=32 time=2ms TTL=255
Reply from 192.168.0.145: bytes=32 time=4ms TTL=255
Reply from 192.168.0.145: bytes=32 time<1ms TTL=255
Reply from 192.168.0.145: bytes=32 time=1ms TTL=255
Reply from 192.168.0.145: bytes=32 time<1ms TTL=255
Reply from 192.168.0.145: bytes=32 time<1ms TTL=255
Reply from 192.168.0.145: bytes=32 time<1ms TTL=255
Reply from 192.168.0.145: bytes=32 time=1ms TTL=255
Reply from 192.168.0.145: bytes=32 time<1ms TTL=255
Reply from 192.168.0.145: bytes=32 time<1ms TTL=255
Ping statistics for 192.168.0.145:
Packets: Sent = 10, Received = 10, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 4ms, Average = 0ms

Ok. I am stupid. The mistake was here:
I created freeRTOS task, where I call two functions in loop every 5 milliseconds.
THIS IS WRONG:
extern void TCP_connection(void *pvParameters)
{
UNUSED(pvParameters);
const portTickType xDelayTime = 5 / portTICK_RATE_MS;
struct tcp_pcb *tcp_server;
tcp_server = tcp_new();
if (tcp_bind(tcp_server, IP_ADDR_ANY, TCP_PORT) != ERR_OK)
return;
while (1){
tcp_server = tcp_listen(tcp_server);
tcp_accept(tcp_server, server_accept);
vTaskDelay(xDelayTime);
}
}
THIS IS GOOD
extern void TCP_connection(void *pvParameters)
{
UNUSED(pvParameters);
const portTickType xDelayTime = 5 / portTICK_RATE_MS;
struct tcp_pcb *tcp_server;
tcp_server = tcp_new();
if (tcp_bind(tcp_server, IP_ADDR_ANY, TCP_PORT) != ERR_OK)
return;
tcp_server = tcp_listen(tcp_server);
tcp_accept(tcp_server, server_accept);
while (1){
vTaskDelay(xDelayTime);
}
}

Related

ESP8266 tcp recv returning errno 11 (EAGAIN) when handling large amounts of data

I am running ESP8266_RTOS_SDK_3.4 for an app that uses TCP to talk to a private port on a local server. In normal operation, it uploads large amounts of data to the server and receives acknowledgements that are usually less than 200 bytes: this always works fine. When I do an OTA update, where it's mainly receiving data, TCP recv fails on attempting to read the first block, and errno is set to 11 (EAGAIN). Even if I make the server send just 1024 bytes, the same thing happens.
This is the TCP connect and recv code:
bool net_tcp_connect (SENDER_DESTINATION * dest) {
struct sockaddr_in destAddr;
if (!find_host (dest->hostname)) {
return false;
}
memset(&destAddr, 0, sizeof(destAddr));
memcpy (&destAddr.sin_addr, findhost_ip (), sizeof (destAddr.sin_addr));
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons (dest->port);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
LOGEF("Create: errno %d", errno);
return false;
}
struct timeval tv;
tv.tv_sec = dest->timeout;
tv.tv_usec = 0;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
if (connect(sock, (struct sockaddr *)&destAddr, sizeof(destAddr)) != 0) {
LOGEF("Connect: %s %d errno %d", findhost_str (), dest->port, errno);
EVENT_HERE ( );
net_tcp_close ();
return false;
}
return true;
}
// --------------------------------------------------------------------------------------------
int net_tcp_recv (void * buffer, int max_length) {
if (sock < 0)
return false;
int bytes_received = recv (sock, buffer, max_length, 0);
if (bytes_received < 0) {
LOGEF("Receive: errno= %d", errno);
net_tcp_close ();
bytes_received = 0;
}
return bytes_received;
}
EAGAIN can be a sign of a receive timeout, but the timeout is set to 30 seconds and the server usually sends out the first 32k bytes in less than a second.
The ESP8266 code does run OK on some access points and, as far as I can tell, the same code on an ESP32 runs OK on all access points.
Any suggestions for why this might happen, or things that I could try changing in the code or the ESP setup to make it work reliably on any access point?

ESP32: Send a simple TCP Message and receive the response

I want to do the same request as with the netcat "nc" command on my computer with an ESP32:
Computer:
$ nc tcpbin.com 4242
Test
Test
What I've tried so far:
Create a wifi client and listen to an answer:
Connect to a tcp server
write a message
wait and read the answer
#include <Arduino.h>
#include <WiFi.h>
WiFiClient localClient;
const char* ssid = "...";
const char* password = "...";
const uint port = 4242;
const char* ip = "45.79.112.203"; // tcpbin.com's ip
void setup() {
Serial.begin(115200);
Serial.println("Connect Wlan");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(WiFi.localIP());
}
void loop() {
sendRequest();
delay(200);
}
void sendRequest() {
if(!localClient.connected()) {
if (localClient.connect(ip, port)) {
Serial.println("localClient connected");
localClient.write('A'); //Single char
Serial.println("msg sent");
}
}
if(localClient.connected()) {
Serial.println("Start reading");
if (localClient.available() > 0) {
char c = localClient.read();
Serial.print(c);
}
Serial.println("Stop reading");
}
}
I'm pretty sure that I misunderstood something of the tcp concept during the implementation. However, after various approaches and trying other code snippets, I can't come up with a solution.
thank you in advance
regards
Leon
There are several issues with your code.
If you test nc, you will notice that the server will not acknowledge back until your press 'return'. You are sending a single byte without termination in your code, so the server is waiting for subsequent data. To terminate the data, you need to send a '\n', or instead of using client.write('A'), use client.println('A').
A network response take time, your current code expecting immediate response without waiting with if (localClient.available() > 0).
Here is the code that will work:
void sendRequest() {
if (localClient.connect(ip, port)) { // Establish a connection
if (localClient.connected()) {
localClient.println('A'); // send data
Serial.println("[Tx] A");
}
while (!localClient.available()); // wait for response
String str = localClient.readStringUntil('\n'); // read entire response
Serial.print("[Rx] ");
Serial.println(str);
}
}

ESP8266 WiFiUDP sending packet causes hang and then crash

I am building a C# windows form program that will communicate with an ESP8266. I am hoping to not have to post too much code as the both the programs are fairly large. I will try to explain my issue as best as I can;
The C# program is sending a packet over UDP broadcast while connected to the ESP8266 soft access point. The ESP8266 can receive and parse the packet just fine from the C# form. The problem is I am trying to send a response packet immediately back to the C# form. This is where the problem is occurring. The ESP8266 will get hung/freeze for a bit either when calling the "write()" or when calling "endPacket()" and then it will crash. Sometimes "endPacket()" will actually not get hung/freeze and send the response packet back, but it will still crash immediately after.
The error output most of the time seems to be: "ets Jan 8 2013,rst cause:4, boot mode:(3,6)". However sometimes it is different.
I have tried using the "yield()" function throughout my code as well but no luck.
Any guidance or solutions are appreciated!?
ESP8266 Program: Main code in question:
bool BatteryOptimizer::ProcessData()
{
size_t enc_data_len = 0;
size_t dec_data_len = 0;
//int ass_data_size_temp = 0;
char encrypted_data[BO_UDP_PACKET_SIZE];
char decrypted_data[BO_UDP_PACKET_SIZE];
char associated_data_temp[BO_AES_ASSOCIATED_DATA_SIZE];
uint8_t iv[GCM_AES_256_IV_TAG_SIZE];
uint8_t tag[GCM_AES_256_IV_TAG_SIZE];
bool status = false;
uint8_t msg_type = 0;
char response_packet[BO_PACKET_SIZE];
size_t response_packet_size = BO_PACKET_SIZE;
msg_type = (uint8_t)BatteryOptimizer::collector_manager->fields[1].ui64_field; //Get Msg Type
//See if Message type is correct first before continuing
if (msg_type < BO_AES_ASSOCIATED_DATA_SIZE)
{
enc_data_len = (size_t)(collector_manager->fields[3].ui64_field - GCM_AES_256_IV_TAG_SIZE); //Get encrypted data length
memcpy(iv, BatteryOptimizer::collector_manager->fields[2].c_array, GCM_AES_256_IV_TAG_SIZE); //Get IV
memcpy(encrypted_data, BatteryOptimizer::collector_manager->fields[3].c_array, enc_data_len); //Get encrypted data
memcpy(tag, BatteryOptimizer::collector_manager->fields[3].c_array + enc_data_len, GCM_AES_256_IV_TAG_SIZE); //Get tag
//ass_data_size_temp = BatteryOptimizer::associated_data[msg_type].length(); //Get associated data legnth
BatteryOptimizer::associated_data[msg_type].toCharArray(associated_data_temp, BO_AES_ASSOCIATED_DATA_SIZE); //Get associated data
//Decrypt data
Serial.println("ProcessData: Attempting to decrypt data!");
status = Decrypt_GCM_AES256((uint8_t *)encrypted_data,
enc_data_len,
iv,
tag,
associated_data_temp,
(uint8_t *)decrypted_data,
&dec_data_len);
if (true == status)
{
//Execute command:
BatteryOptimizer::ExecuteCommand(msg_type, decrypted_data, dec_data_len);
//Build Reponse packet:
Serial.println("ProcessData: Attempting to build Reponse packet!");
memset(response_packet, 0, BO_PACKET_SIZE);
BatteryOptimizer::BuildResponsePacket(associated_data_temp, response_packet, &response_packet_size);
//Send Response packet:
Serial.println("ProcessData: Attempting to begin packet!");
Serial.println("ProcessData: Remote IP: ");
Serial.println(BatteryOptimizer::udp_server.remoteIP());
Serial.println("ProcessData: Remote Port: ");
Serial.println(BatteryOptimizer::udp_server.remotePort());
status = BatteryOptimizer::udp_server.beginPacket(BatteryOptimizer::udp_server.remoteIP(), BatteryOptimizer::udp_server.remotePort());
if (true == status)
{
Serial.println("ProcessData: Attempting to write packet!");
Serial.println(BatteryOptimizer::udp_server.write(response_packet, response_packet_size));
Serial.println("ProcessData: Attempting to send packet!");
status = BatteryOptimizer::udp_server.endPacket();
if (true == status)
{
Serial.println("ProcessData: UDP server sent reponse packet!");
}
else
{
Serial.println("ProcessData: UDP server was unable to send repsonse packet!");
Serial.println("ProcessData: Tried to send response packet: " + BatteryOptimizer::associated_data[msg_type]);
}
}
else
{
Serial.println("ProcessData: UDP server was unable to begin packet!");
Serial.println("ProcessData: Tried to send response packet: " + BatteryOptimizer::associated_data[msg_type]);
}
}
else
{
Serial.println("ProcessData: Failed to process data!");
//Testing
Serial.println("Encrypted length: ");
Serial.println(enc_data_len);
Serial.println("Decrypted Data: ");
Serial.println(decrypted_data);
Serial.println(decrypted_data + 50);
Serial.println("Associated Data: ");
Serial.println(associated_data_temp);
}
}
return status;
} //END ProcessData
void BatteryOptimizer::UDP_ServerLoop()
{
char packet[BO_UDP_PACKET_SIZE];
int packetSize;
Serial.println("UDP server about to start parsing packets!");
//while (BatteryOptimizer::run_udp == true)
if (BatteryOptimizer::run_udp == true)
{
packetSize = BatteryOptimizer::udp_server.parsePacket();
if (packetSize > 0)
{
Serial.println("Received packet! Size: ");
Serial.println(packetSize);
size_t len = (size_t)BatteryOptimizer::udp_server.read(packet, BO_UDP_PACKET_SIZE);
if (len > 0)
{
BatteryOptimizer::collector_manager->Collect(packet, &len);
if (COLLECT_FOUND == BatteryOptimizer::collector_manager->status)
{
Serial.println("Found msg!");
Serial.println("Collected Packet Size:");
Serial.println(BatteryOptimizer::collector_manager->packet_size);
BatteryOptimizer::collector_manager->Check_Checksum();
if (COLLECT_VALID_CS == BatteryOptimizer::collector_manager->status)
{
Serial.println("Valid Checksum!");
BatteryOptimizer::collector_manager->Parse();
//Process data
if (true == BatteryOptimizer::ProcessData())
{
Serial.println("Process success!");
}
}
else
{
Serial.println("Invalid Checksum!");
}
BatteryOptimizer::collector_manager->ResetCache();
}
else
{
Serial.println("Did not find a message!");
}
}
else
{
Serial.println("Did not receive a complete packet!");
}
}
else
{
Serial.println("Packet size is 0!");
}
Serial.println("Packet received: ");
Serial.println(packet);
delay(BO_UDP_DELAY);
} //END run_udp loop
Serial.println("UDP server no longer parsing packets! ");
} //END UDP_ServerLoop
void BatteryOptimizer::UDP_StartServer()
{
if (BatteryOptimizer::is_udp_running == false)
{
Serial.println("Starting UDP server. ");
BatteryOptimizer::udp_server.begin(BO_UDP_PORT);
Serial.println("Listening on UDP port ");
Serial.println(BO_UDP_PORT);
BatteryOptimizer::run_udp = true;
BatteryOptimizer::is_udp_running = true;
}
} //END UDP_StartServer
C# Windows Form: Main code in question:
private void UDP_Initialize_Client()
{
//Start UDP server to listen in for the Battery Opetimizer device:
udp_client = new UdpClient( listenPort );
end_point = new IPEndPoint( IPAddress.Broadcast, listenPort );
udp_client.EnableBroadcast = true;
udp_client.MulticastLoopback = false;
}
private void UDP_ReceiveContinuously( IAsyncResult res )
{
byte[] received = udp_client.EndReceive( res, ref end_point );
//Process Data:
UDP_ProcessData( ref received );
UDP_SetupReceive();
} //END UDP_ReceiveContinuously
private void UDP_SetupReceive()
{
try
{
udp_client.BeginReceive( new AsyncCallback( UDP_ReceiveContinuously ), null );
}
catch (Exception e)
{
MessageBox.Show( e.ToString() );
}
} //END UDP_SetupReceive
As an update, I figured out how to use the exception decoder. Here are is the output;
0x40206afe: raise_exception at core_esp8266_postmortem.cpp line ?
0x40206b10: __assert_func at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/core_esp8266_postmortem.cpp line 275
0x40100ba2: get_unpoisoned_check_neighbors at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_local.c line 125
0x402074bd: uart_write at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/uart.cpp line 509
0x40100c91: umm_poison_free_fl at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_local.c line 148
0x40205690: HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/HardwareSerial.h line 164
0x4010038c: free at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/heap.cpp line 259
0x40205690: HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/HardwareSerial.h line 164
0x4020ebe5: operator delete(void*) at /workdir/repo/gcc/libstdc++-v3/libsupc++/del_op.cc line 48
0x4020ebd0: operator delete[](void*) at /workdir/repo/gcc/libstdc++-v3/libsupc++/del_opv.cc line 33
0x40204b40: Collector::FreeUnnecessaryResources() at D:\Projects\Arduino\libraries\DataHandler/DataHandler.cpp line 331 (discriminator 3)
0x40201912: BatteryOptimizer::UDP_OnPacket(AsyncUDPPacket) at C:\Users\SPENCE~1\AppData\Local\Temp\arduino_build_863316\sketch/battery_optimizer.cpp line 312 (discriminator 1)
0x4020105f: BP_OnPacket(AsyncUDPPacket&) at D:\Projects\Arduino\ESP8266\BatteryPerserver/BatteryPerserver.ino line 55
0x40208910: precache at ?? line ?
0x40102b12: wDev_ProcessFiq at ?? line ?
0x402082c0: std::_Function_handler ::_M_invoke(std::_Any_data const&, AsyncUDPPacket&) at c:\users\spencerbell\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\2.5.0-4-b40a506\xtensa-lx106-elf\include\c++\4.8.2/functional line 2073
0x40202da2: AsyncUDP::_recv(udp_pcb*, pbuf*, ip4_addr*, unsigned short) at D:\Projects\Arduino\libraries\ESPAsyncUDP\src/AsyncUDP.cpp line 197
0x40208910: precache at ?? line ?
0x40221f4b: cnx_start_handoff_cb at ?? line ?
0x401009a5: check_poison_neighbors$part$3 at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_local.c line 71
0x40100a61: umm_malloc_core at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_malloc.cpp line 458
0x40101a17: ppCalFrameTimes at ?? line ?
0x40202dd8: AsyncUDP::_s_recv(void*, udp_pcb*, pbuf*, ip4_addr const*, unsigned short) at D:\Projects\Arduino\libraries\ESPAsyncUDP\src/AsyncUDP.cpp line 210
0x4021314c: udp_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/udp.c line 404
0x4022eb18: pbuf_alloc at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-esp/lwip-esp.c line 669
0x40217cf0: ip4_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/core/ipv4/ip4.c line 1461
0x40100c77: umm_free at C:\Users\SpencerBell\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\umm_malloc/umm_malloc.cpp line 398
0x4020f349: ethernet_input_LWIP2 at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/lwip2-src/src/netif/ethernet.c line 188
0x4020f168: esp2glue_ethernet_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-lwip/lwip-git.c line 469
0x4022ebfe: ethernet_input at /local/users/gauchard/arduino/arduino_esp8266/esp8266-lwip/tools/sdk/lwip2/builder/glue-esp/lwip-esp.c line 365
Well after weeks of searching and modifying code. I figured out I was simply just using too much memory. I found several places in my code where I cut down array sizes and now its working perfect!
As a note, I also switched to using the ESPAsyncUDP library: https://github.com/me-no-dev/ESPAsyncUDP

ESP32 TCP client

I want to set up TCP server on windows and TCP client on ESP32. Main idea is to send String to ESP32 change it and send it back to server, but I'm really new with all of this stuff and got stuck on setting up TCP client on ESP32. Examples or references would be really helpful.
int create_ipv4_socket()
{
struct addrinfo hints;
struct addrinfo *res;
struct in_addr *addr;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
int err = getaddrinfo(UDP_IPV4_ADDR, TCP_PORT, &hints, &res);
if(err != 0 || res == NULL) {
printf("DNS lookup failed err=%d res=%p\n", err, res);
return -1;
}
/* Code to print the resolved IP.
Note: inet_ntoa is non-reentrant, look at ipaddr_ntoa_r for "real" code */
addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
printf("DNS lookup succeeded. IP=%s\n", inet_ntoa(*addr));
l_sock = socket(res->ai_family, res->ai_socktype, 0);
if(l_sock < 0) {
printf("... Failed to allocate socket.\n");
freeaddrinfo(res);
return -1;
}
struct timeval to;
to.tv_sec = 2;
to.tv_usec = 0;
setsockopt(l_sock,SOL_SOCKET,SO_SNDTIMEO,&to,sizeof(to));
if(connect(l_sock, res->ai_addr, res->ai_addrlen) != 0) {
printf("... socket connect failed errno=%d\n", errno);
close(l_sock);
freeaddrinfo(res);
return -1;
}
printf("... connected\n");
freeaddrinfo(res);
// All set, socket is configured for sending and receiving
return l_sock;
}
From this forum https://www.esp32.com/viewtopic.php?t=5965
How do you communicate with your ESP? if you communicate through UART, just send him AT command he need by writing on the UART port:
"AT+CIPSTATUS\r\n"
and then wait for his response.
If you are connected to your ESP32 directly with your computer, just use putty and directly send AT command to it.
A non exhaustive list of AT's command can be found here:
https://www.espressif.com/sites/default/files/documentation/esp32_at_instruction_set_and_examples_en.pdf

While STM32 runs the LwIP protocol,How to implement 5 TCP connections?

Now,I am working with STM32F107+lwip.The aim is making a gateway which is used to exchange datas between ETHERNET and CAN. The UDP server is tested well.And now I want to increase the TCP server function,which can be permitted to establish 5 TCP connections.
My questions:
1 TCP connnection is tested ok,How to implement 5 TCP connections?
First,PC send data to STM32 by TCP connections. STM32 receives it and send it to CAN.Then,when STM32 receives datas from CAN ,it will send the datas to PC by all the TCP connections.Now,my idea is that typedef a structure,when STM32 received the data from PC,it will record the pcb,remote ip and remote port. And receiving data from CAN ,STM32 will send it through the recording data.The result is the data will be sent slowly when STM32 invokes the "tcp_write()" and "tcp_output"frequently.
So I wonder the solutions to implement multiple TCP connections.
#define TCP_WORKING 0xaa
#define TCP_FREE 0xa5
typedef struct Cmd_TCPData
{
unsigned char TCP_STATUS;
unsigned char cmd_flag;
unsigned short remote_port;
unsigned short data_len;
struct ip_addr remote_ip;
unsigned char *pData;
struct tcp_pcb *TCP_pcb;
}Cmd_TCPData;
Cmd_TCPData cmd_tcp;
Cmd_TCPData tcp_list[5];
static u8 TcpListNum;
void TCP_server_init(void)
{
struct tcp_pcb *pcb;
err_t err;
/*****************************************************/
pcb = tcp_new();
if (!pcb)
{
return ;
}
err = tcp_bind(pcb,IP_ADDR_ANY,devInfo.udpPort);
if(err != ERR_OK)
{
return ;
}
pcb = tcp_listen(pcb);
tcp_accept(pcb,tcp_server_accept);
}
static err_t tcp_server_accept(void *arg,struct tcp_pcb *pcb,err_t err)
{
tcp_setprio(pcb, TCP_PRIO_MIN);
tcp_recv(pcb,tcp_server_recv);
err = ERR_OK;
return err;
}
static err_t tcp_server_recv(void *arg, struct tcp_pcb *pcb,struct pbuf *p,err_t err)
{
struct pbuf *p_temp = p;
int nPos=0;
u8 searchtemp=0;
//TCP_pcbA=pcb;
while(tcp_list[searchtemp].TCP_STATUS==TCP_WORKING)
{
if(tcp_list[searchtemp].remote_ip.addr!= pcb->remote_ip.addr)
{
searchtemp++;
}
else
break;
if(searchtemp==5)
{
searchtemp=0;
break;
}
}
/******copy*******************/
tcp_list[searchtemp].TCP_pcb=pcb;
tcp_list[searchtemp].pData = TCPRecvBuf;
tcp_list[searchtemp].remote_port=pcb->remote_port;
tcp_list[searchtemp].remote_ip = pcb->remote_ip;
tcp_setprio(tcp_list[searchtemp].TCP_pcb, TCP_PRIO_MIN+searchtemp);
if(p_temp != NULL)
{
tcp_recved(pcb, p_temp->tot_len);
while(p_temp != NULL)
{
// tcp_write(pcb,p_temp->payload,p_temp->len,TCP_WRITE_FLAG_COPY);
// tcp_output(pcb);
memcpy(tcp_list[searchtemp].pData+nPos,p_temp->payload,p_temp->len);
nPos += p_temp->len;
p_temp = p_temp->next;
}
}
else
{
tcp_close(pcb);
}
tcp_list[searchtemp].data_len = nPos;
flash_led_tcp = 1;
tcp_list[searchtemp].TCP_STATUS= TCP_WORKING;
TcpListNum=searchtemp;
pbuf_free(p);
err = ERR_OK;
return err;
}
void send_tcp_data(u8_t *pPtr,u16_t data_len)
{
u8 x=0;
while(x<5)
{
if(tcp_list[x].TCP_STATUS==TCP_WORKING)
{
//TCP_pcbA->remote_port=tcp_list[x].remote_port;
//TCP_pcbA->remote_ip= tcp_list[x].remote_ip;
tcp_write(tcp_list[x].TCP_pcb,pPtr,data_len,TCP_WRITE_FLAG_COPY);
tcp_output(tcp_list[x].TCP_pcb);
}
OSTimeDlyHMSM(0, 0, 0, 250);//250ms
x++;
}
}
The tcp_server_accept() will contain the newly created connection. To this connection you can attach your context.
struct myclient_t
{
struct tcp_pcb *pcb;
/* all the variables uniqe for tracking this specific connection.. parser-state, receive/send buffers, statistics... */
int foo;
int bar;
};
static err_t tcp_server_accept(void *arg,struct tcp_pcb *pcb,err_t err)
{
err_t ret_err;
struct struct myclient_t *context = 0;
int i;
context = new_client();
if (!context )
{
return ERR_MEM;
}
context->pcb = pcb;
/* pass newly allocated es structure as argument to newpcb */
tcp_arg(newpcb, context); /* recv, sent, error and poll callbacks will have context their argument, which is uniqe for each connection */
/* initialize lwip tcp_recv callback function for newpcb */
tcp_recv(newpcb, tcp_server_recv
tcp_sent(newpcb, tcp_server_sent);
/* initialize lwip tcp_err callback function for newpcb */
tcp_err(newpcb, tcp_server_error);
/* initialize lwip tcp_poll callback function for newpcb */
tcp_poll(newpcb, tcp_server_poll, 1);
return ERR_OK;
}

Resources