ESP32 TCP client - tcp

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

Related

STM32 LwIP Delay in netconn_write

I implemented a small tcp client on STM32F7 with freeRtos and LwIP and netconn api.
I can establish a connection with the server and send some data to the network. My problem is a huge delay between the command and when I can actually see the ethernet data on the network (seconds..). Seems like the data is buffered before sending it in one go.
I'm aware of the TCP_NODELAY flag and I set it (with tcp_nagle_disable(conn->pcb.tcp)), but it doesn't make a difference. Ethernet payload is around 50 bytes, TCP_MSS is 1460.
The netconn api sees the data as sent (netbuffer structure is updated, tcp_write() and tcp_output() are called with no errors), but I have the impression that after low_level_output() is called and the data buffer is passed to the DMA (with HAL_ETH_TransmitFrame()) it stays there until something happened and 3 or 4 ethernet packets are sent in a go.
I don't want to wait forever for a reply and I set a timeout on netconn_recv(), enabling LWIP_SO_RCVTIMEO and calling netconn_set_recvtimeout(). I set up the server to answer with an echo but even with a timeout of 500ms I loose most of the replies.
Here some code:
conn = netconn_new(NETCONN_TCP);
if (conn != NULL)
{
err = netconn_bind(conn, IP_ADDR_ANY, 0);
if (err == ERR_OK)
{
connect_error = netconn_connect(conn, &dest_addr, SRV_PORT);
if (connect_error == ERR_OK)
{
// set a timeout to avoid waiting forever
netconn_set_recvtimeout(conn, 500);
//TCP_NODELAY
tcp_nagle_disable(conn->pcb.tcp);
osSemaphoreRelease(tcpsem); // signal tcpsend
if (netconn_recv(conn, &buf) == ERR_OK)
{
//Parse message
do
{
// do stuff..
}
while (netbuf_next(buf) >0);
netbuf_delete(buf);
} else {
// TIMEOUT
}
}
/* Close connection */
netconn_close(conn);
}
netconn_delete(conn);
}
vTaskDelete(tcpsendTaskHandle);
vTaskDelete(NULL);
tcpsend
void tcpsend (void *data, size_t len)
{
// send the data to the connected connection
netconn_write(conn, data, len, NETCONN_NOFLAG);
}
tcpsend
static void tcpsend_thread (void *arg)
{
for (;;)
{
// semaphore must be taken before accessing the tcpsend function
osSemaphoreAcquire(tcpsem, portMAX_DELAY);
// build msg
if (ethPrepare(&ethMsg) == ERR_OK)
{
// send the data to the server
tcpsend(&ethMsg, ethMsg.ncSize);
}
vTaskDelay(100);
}
}
Found the problem:
I forgot to set also the TxBuffer memory as not cacheable bufferable..
Once I added the memory configuration on the loader script and in ethernetif.c also for the tx buffer (I had it only for he rx) I could see the ethernet packets right away.

Raspberry PI: endianness CROSS COMPILE

I use buildroot cross toolchain to compile Raspberry application from my computer (Ubuntu X86).
I'm developping a TCP serveur that allows a connection on 5003 (0x138B) TCP port number. When I'm start the server, that's right but my server wait a connection on 35603 (0x8B13) TCP port number (check with netstat -a).
It seems to be an endianness problem but I don't know how to resolve.
Can you help me please?
Thanks.
thanks for your answer.
I agree it's very strange. I don't think the code is the problem. It's working well on other platform.
Please find the code below:
/*Create the server */
int CreateServeur (unsigned short port, int *sock_srv, int nb_connect)
{
int l_ret = -1;
struct sockaddr_in l_srv_addr;
/* address initialisation */
printf("creation serveur port %i\n", port);
memset ((char*) &l_srv_addr,0, sizeof (struct sockaddr_in));
l_srv_addr.sin_family = PF_INET;
l_srv_addr.sin_port = port;
l_srv_addr.sin_addr.s_addr = htonl (INADDR_ANY);
/* main socket creation */
if ((*sock_srv = socket (PF_INET, SOCK_STREAM, 0)) <= 0)
{
printf("server socket creation error");
}
else
{
if (bind (*sock_srv, (struct sockaddr *) &l_srv_addr, sizeof (struct sockaddr_in)) == -1)
{
close (*sock_srv);
printf("bind socket error");
}
else
{
if (listen (*sock_srv, nb_connect) == ERROR)
{
close (*sock_srv);
printf("listen socket error");
}
else
{
l_ret = 0;
}
}
}
return (l_ret);
}
This function doesn't return any error. The first log (printf("creation serveur port %i\n", port);) display the good port (5003) but the server wait connexion on port 35603 (netstat -a).
If it's not a endianness problem, I don't understand.

Windows 7 upgrade, UDP Broadcast issue

I am new to this environment as far as UDP protocols and sending/receiving data via networks. I have read the other post regarding this kind of issue but I am not sure how to fix my problem:
I have just upgraded a PC to Windows 7 from XP. This upgrade was due to my application needs to run on Win7. I have NOT changed the was our UDP stream is broadcasted. With the upgrade I can no longer run the older version of my application becasue the UDP stream doesn't seam to get to my application.
I have turned off all firewalls and am running everything as admin.
This is how my setup is:
Code is running on ip: 192.168.2.1
UDP is sent from 192.168.2.1 to 192.168.2.87 and then broadcasted to 192.168.2.255
I used to be able to see this UDP stream with my old application on a seperate computer: 192.168.2.12
If I change my UDP stream to go directly to 192.168.2.12 ip, then my application works, but then the UDP is not broadcasted anymore. I need the UDP to be able to be read by more than one computer.
Here is my wireshark out put for the UDP Stream:
Source: 192.168.2.87
Destination: 192.168.2.255
Protocol: UDP Info:
Sorce Port: 6601 Destination Port: 6601
I have tried hard coding my c-code to listen to any possibility I can think of, aka the sender addr function:
senderAddr.sin_addr.s_addr = htonl(INADDR_ANY);
To something like:
senderAddr.sin_addr.s_addr = inet_addr("192.168.2.212")
This is the code to init the I/O buffer:
// UDP Receiver Declarations -
SOCKET SockIn = INVALID_SOCKET;
SOCKADDR_IN senderAddr;
int senderSize = sizeof(senderAddr);
u_short PortIn = 6601;
int timeout = 1;
//===================<Callbacks::Callbacks>==================
//
// Summary: Constructor
//
//=============================================================================
Callbacks::Callbacks(RTUserIntegrationI &a_rIntegration)
: m_rIntegration(a_rIntegration)
, m_pUDPInput(NULL)
{
}
//=====================<Callbacks::~Callbacks>===============
//
// Summary: Destructor
//
//=============================================================================
Callbacks::~Callbacks()
{
}
//=====================<Callbacks::InitIOBuffers>====================
//
// Summary: Init function for the IO buffer
//
//=============================================================================
void Callbacks::vInitIOBuffers()
{
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
WSADATA WSAData;
UInt Size = 0;
// UDP Declarations -
// Initialize the member pointers to buffers
bufferin = m_rIntegration.pGetIOBuffer(Input_Buffer);
if (bufferin != NULL)
m_pUDPInput = static_cast<InputData*>(bufferin->pGetDataAddress(Size));
// UDP Receive -
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
{
printf("\nCould not open WSA connection");
WSACleanup();
}
SockIn = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SockIn == INVALID_SOCKET)
{
printf("\nCould not create socket.");
closesocket(SockIn);
WSACleanup();
}
senderAddr.sin_family = AF_INET;
senderAddr.sin_port = htons(PortIn);
senderAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (setsockopt(SockIn, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptVal, bOptLen) != INVALID_SOCKET)
{
printf("\nSet SO_REUSEADDR: ON.");
}
if (bind(SockIn, (struct sockaddr *) &senderAddr, senderSize) == -1)
{
printf("\nCould not bind socket.");
closesocket(SockIn);
WSACleanup();
}
setsockopt(SockIn, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
}
I have the receive port number hard coded to 6601.
The code above works fine and the computer sees and reads the broadcasted UDP in Windows XP but ceases to work in Windows 7.
Any suggestions would be greatly appreciated.
ADDED:
192.168.2.1 generates the UDP stream--->sent to 192.168.2.87---> broadcasted on 192.168.2.255 ---> Notheing has changed on any of those computers....... I then have two computers (one XP and one Windows 7) than listen to the 2.255 ip. XP is getting the UDP and Win7 is not.

TCP server accept call does not return

We need some help with a TCP client server code. The client timesout from its connect call and the server does not return from accept. Here's the strace.
strace -p 7167 -p 7168 -p 7297
Process 7167 attached - interrupt to quit
Process 7168 attached - interrupt to quit
Process 7297 attached - interrupt to quit
[pid 7167] accept(4, <unfinished ...>
[pid 7168] accept(4, <unfinished ...>
[pid 7297] connect(3, {sa_family=AF_INET, sin_port=htons(24465), sin_addr=inet_addr("215.47.142.168")}, 16
We rebooted the system but the problem persists even immediately after reboot.
Could it be a SYN Flood problem. How do we deal with such connections? Also, do the half made connections queue up in the listen queue(argument 2 of listen call) and stop any further accepts from any client OR does the TCP some how blocks that particular client only.
Here's the code...
client.all this is inside a function that returns socket
int sock = socket(nmspace,style,protocol);
int ret;
struct hostent *hinfo;
if(sock<0){
printf("Error occurred while creating socket:%d\n",sock);
printf("%s\n",strerror(errno));
return -1;
}
memset(&dest, 0, sizeof(struct sockaddr_in));
hinfo = gethostbyname(rmserver);
if(hinfo == NULL)
printf("getbyname failed!\n");
dest.sin_family = AF_INET;
dest.sin_addr = *(struct in_addr *)(hinfo->h_addr);
dest.sin_port = htons(port);
ret = connect(sock, (struct sockaddr *)&dest, sizeof(struct sockaddr));
if(ret<0){
printf("Error occurred while connecting on the socket:%d\n",sock);
printf("%s\n",strerror(errno));
close(sock);
return -1;
}
server
making the server socket...all this is inside a function that returns the socket>>>>>>
struct sockaddr_in serv;
int mysocket,r;
mysocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv, 0, sizeof(struct sockaddr_in));
serv.sin_family = AF_INET;
serv.sin_addr.s_addr = INADDR_ANY;
serv.sin_port = htons(port);
r = bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr));
if(r<0) {
printf("Error occurred binding the socket:%d to the server port:%d\n",mysocket,port);
printf("%s",strerror(errno));
close(mysocket);
return -1;
}
r = listen(mysocket, 5);
if(r<0) {
printf("Error occurred while enabling listen on the socket:%d\n",mysocket);
printf("%s",strerror(errno));
close(mysocket);
return -1;
}
server accept call>>>>>>
struct sockaddr_in dest;
int socksize=sizeof(struct sockaddr_in);
int consocket;
consocket = accept(sock, (struct sockaddr *)&dest, (socklen_t *)&socksize);
if(consocket<0) {
printf("Error occurred while accepting on the socket:%d\n",sock);
printf("%s\n",strerror(errno));
}
Not using select. I hope we don't need that as the sockets are by default blocking.
cheers...raman
Your client should be using connect (man page) rather than accept. Servers use accept to accept incoming connections and to get a new socket unique to that connection, leaving the original file descriptor free for listening and accepting new connections. Clients just use the same socket after the connection is made.
Also, I recommend taking a look at how to use select (man page).

Problem in listening to multicast in C++ with multiple NICs

I am trying to write a multicast client on a machine with two NICs, and I can't make it work. I can see with a sniffer that once I start the program the NIC (eth4) start receiving the multicast datagrams, However, I can't recieve() any in my program.
When running "tshark -i eth4 -R udp.port==xxx (multicast port)"
I get:
1059.435483 y.y.y.y. (some ip) -> z.z.z.z (multicast ip, not my eth4 NIC IP) UDP Source port: kkk (some other port) Destination port: xxx (multicast port)
Searched the web for some examples/explanations, but it seems like I do what everybody else does. Any help will be appreciated. (anything to do with route/iptables/code?)
bool connectionManager::sendMulticastJoinRequest()
{
struct sockaddr_in localSock;
struct ip_mreqn group;
char* mc_addr_str = SystemManager::Instance()->getTCP_IP_CHT();
char* local_addr_str = SystemManager::Instance()->getlocal_IP_TOLA();
int port = SystemManager::Instance()->getTCP_Port_CHT();
/* Create a datagram socket on which to receive. */
CHT_UDP_Feed_sock = socket(AF_INET, SOCK_DGRAM, 0);
if(CHT_UDP_Feed_sock < 0)
{
perror("Opening datagram socket error");
return false;
}
/* application to receive copies of the multicast datagrams. */
{
int reuse = 1;
if(setsockopt(CHT_UDP_Feed_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
{
perror("Setting SO_REUSEADDR error");
close(CHT_UDP_Feed_sock);
return false;
}
}
/* Bind to the proper port number with the IP address */
/* specified as INADDR_ANY. */
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(port);
localSock.sin_addr.s_addr =inet_addr(local_addr_str); // htonl(INADDR_ANY); //
if(bind(CHT_UDP_Feed_sock, (struct sockaddr*)&localSock, sizeof(localSock)))
{
perror("Binding datagram socket error");
close(CHT_UDP_Feed_sock);
return false;
}
/* Join the multicast group mc_addr_str on the local local_addr_str */
/* interface. Note that this IP_ADD_MEMBERSHIP option must be */
/* called for each local interface over which the multicast */
/* datagrams are to be received. */
group.imr_ifindex = if_nametoindex("eth4");
if (setsockopt(CHT_UDP_Feed_sock, SOL_SOCKET, SO_BINDTODEVICE, "eth4", 5) < 0)
return false;
group.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
group.imr_address.s_addr = htonl(INADDR_ANY); //also tried inet_addr(local_addr_str); instead
if(setsockopt(CHT_UDP_Feed_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
{
perror("Adding multicast group error");
close(CHT_UDP_Feed_sock);
return false;
}
// Read from the socket.
char databuf[1024];
int datalen = sizeof(databuf);
if(read(CHT_UDP_Feed_sock, databuf, datalen) < 0)
{
perror("Reading datagram message error");
close(CHT_UDP_Feed_sock);
return false;
}
else
{
printf("Reading datagram message...OK.\n");
printf("The message from multicast server is: \"%s\"\n", databuf);
}
return true;
}
Just a thought, (I've not done much work with multicast), but could it be because you're binding to a specific IP address? The socket could be only accepting packets destined for it's bound IP address and rejecting the multicast ones?
Well, there is some time ago since I didn't play with multicast. Don't you need root/admin rights to use it? did you enable them when launching your program?

Resources