UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
5,522 Views
Registered: ‎05-13-2016

Extending the LWIP Echo Server

Jump to solution

I am looking at the Echo Server, it basically it listens for an incoming packet, and when it receives it, it transmits it back out, in the same task.  I believe I will need to split that into two tasks, as I will need to transmit data, independent of what has been received. This design would be much more useful if the transmit and receive had been separated and they had been tied together with a Queue.  That way it would echo, but would make it very easy to hack into and use! (My two cents).

 

So here is what I am looking at doing

 

 

Here is the echo thread.  I changed the name and added comments to where I think I need to glue in the TX thread

 

void RX_TX_application_thread(void *)

{

       int sock, new_sd;

       struct sockaddr_in address, remote;

       int size;

 

       if ((sock = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0)

              return;

 

       address.sin_family = AF_INET;

       address.sin_port = htons(echo_port);

       address.sin_addr.s_addr = INADDR_ANY;

 

       if (lwip_bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0)

              return;

 

       lwip_listen(sock, 0);

 

       size = sizeof(remote);

 

       while (1) {

              if ((new_sd = lwip_accept(sock, (struct sockaddr *)&remote, (socklen_t *)&size)) > 0) {

                     sys_thread_new("RX packet", process_rx_request,

                           (void*)new_sd,

                           THREAD_STACKSIZE,

                           DEFAULT_THREAD_PRIO);

              }

/************************* New Code Here *****************************************************************************

*                                 call process_rx_request which has semaphore or checks queue

*                                 

 

***********************************************************************************************************************/

}

 

 

Here is the original lower level echo code, removing the nwrote = write(sd, recv_buf, n))” section of code.

 

/* thread spawned for each connection */

void process_rx_request(void *p)

{

       int sd = (int)p;

       int RECV_BUF_SIZE = 2048;

       char recv_buf[RECV_BUF_SIZE];

       int n, nwrote;

       int i;

 

       while (1) {

              /* read a max of RECV_BUF_SIZE bytes from socket */

              if ((n = read(sd, recv_buf, RECV_BUF_SIZE)) < 0) {

                     xil_printf("%s: error reading from socket %d, closing socket\r\n", __FUNCTION__, sd);

                     break;

              }

 

              if(n>0){

                     xil_printf("%d characters recieved\n\r",n);

                     for(i=0;i<n;i++){

                           xil_printf("%c",recv_buf[i]);

                     }

                     xil_printf("\n\r");

              }

 

              /* break if the recved message = "quit" */

              if (!strncmp(recv_buf, "quit", 4))

                     break;

 

              /* break if client closed connection */

              if (n <= 0)

                     break;

 

              /* handle request */

       }

 

 

I am going to create a new task, process_tx_request, that pulls the “nwrote = write(sd, recv_buf, n))” from the echo code.  It looks like this calls LWIP_SEND.

 

 

void process_tx_request(void *p)

{

       int sd = (int)p;

       int RECV_BUF_SIZE = 2048;

       char recv_buf[RECV_BUF_SIZE];

       int n, nwrote;

       int i;

 

       while (1) {

/***********************************************Insert code **************************************

*

*                    wait on semaphore or queue  -  have to feed in buffer/queue

*

***************************************************************************************************

 

              if ((nwrote = write(sd, recv_buf, n)) < 0) {

                     xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d\r\n",

                                  __FUNCTION__, n, nwrote);

                     xil_printf("Closing socket %d\r\n", sd);

                     break;

              }

       }

 

}

 

Is there a better way to go about this, or code that offers a better starting point.  In the above code, for the RX section, longer term I think this should go to an input queue that my application can process.  Similarly, the transmit section would also be feed from a queue.  Can I just call the "wrote = write(sd, recv_buf, n)) < 0)" function as described above

 

0 Kudos
1 Solution

Accepted Solutions
9,538 Views
Registered: ‎05-13-2016

Re: Extending the LWIP Echo Server

Jump to solution

OK figured it out. Here is the server code.  I basically created the

 

/****************************************************************************************

* Server Application

*********************************************************************************/

void server_application_thread(void *)

{

int sock, new_sd;

struct sockaddr_in address, remote;

int size;

 

if ((sock = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0)

return;

 

address.sin_family = AF_INET;

address.sin_port = htons(echo_port);

address.sin_addr.s_addr = INADDR_ANY;

 

if (lwip_bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0)

return;

 

lwip_listen(sock, 0);

 

size = sizeof(remote);

 

while (1) {

if ((new_sd = lwip_accept(sock, (struct sockaddr *)&remote, (socklen_t *)&size)) > 0) {

sys_thread_new("RX packet", process_rx_request,

(void*)new_sd,

THREAD_STACKSIZE,

DEFAULT_THREAD_PRIO);

sys_thread_new("TX packet", process_tx_request,

(void*)new_sd,

THREAD_STACKSIZE,

DEFAULT_THREAD_PRIO);

}

}

}

 To test, I added an echo process that takes data out of the receive Queue and places it in the transmit queue

0 Kudos
6 Replies
5,502 Views
Registered: ‎05-13-2016

Re: Extending the LWIP Echo Server

Jump to solution

OK, I am darn close, but unfortunately something is missing when I try to send data out.  I am sure I probably don't have a socket open or something like that.

 

Again, I separated the RX and TX steps into two threads, and interconnected them via a queue.

 

Specifically, the RX process receives the data and stuffs it into an input queue.

 

I added a echo process that takes data out of the input queue and stuffs it into an output queue.

 

Finally, the TX process takes the data out of the output queue and attempts to transmit the data. This is were it fails.

 

Here is the output;

 

 

-----lswIP Socket Mode Echo server Demo Application ------
Board IP: 192.168.1.10
Netmask : 255.255.255.0
Gateway : 192.168.1.1
link speed: 1000

              Server   Port Connect With..
-------------------- ------ --------------------
         echo server      7 $ telnet <board_ip> 7

7 characters received
Contents of RX buffer
hell0


In TX routine
Number of elements in message is 7
Contents of TX buffer
hell0

process_tx_request: ERROR responding to client echo request. received = 7, written = -1
Closing socket 1

 

 

The source file is attached

0 Kudos
9,539 Views
Registered: ‎05-13-2016

Re: Extending the LWIP Echo Server

Jump to solution

OK figured it out. Here is the server code.  I basically created the

 

/****************************************************************************************

* Server Application

*********************************************************************************/

void server_application_thread(void *)

{

int sock, new_sd;

struct sockaddr_in address, remote;

int size;

 

if ((sock = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0)

return;

 

address.sin_family = AF_INET;

address.sin_port = htons(echo_port);

address.sin_addr.s_addr = INADDR_ANY;

 

if (lwip_bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0)

return;

 

lwip_listen(sock, 0);

 

size = sizeof(remote);

 

while (1) {

if ((new_sd = lwip_accept(sock, (struct sockaddr *)&remote, (socklen_t *)&size)) > 0) {

sys_thread_new("RX packet", process_rx_request,

(void*)new_sd,

THREAD_STACKSIZE,

DEFAULT_THREAD_PRIO);

sys_thread_new("TX packet", process_tx_request,

(void*)new_sd,

THREAD_STACKSIZE,

DEFAULT_THREAD_PRIO);

}

}

}

 To test, I added an echo process that takes data out of the receive Queue and places it in the transmit queue

0 Kudos
Highlighted
5,445 Views
Registered: ‎05-13-2016

Re: Extending the LWIP Echo Server

Jump to solution

 

So,  I further modified the code to support multiple sockets. I am able to open up multiple telnet sessions and have them each echo.  I now have an echo design that I can pull out the echo task, and bolt up to my system and do something useful.

 

 

 

ENET_RX.jpg

 

 

 

ENET_tx.jpg

 

 

 

 

 

 

ENET_echo.jpg

 

 

ENET_packet.jpg

 

 

Tags (2)
0 Kudos
5,438 Views
Registered: ‎05-13-2016

Re: Extending the LWIP Echo Server

Jump to solution

Code for echo is attached.

 

Here is code added to main.c and main.h

 

/********************************************************************************************************************************

*Main.h

***************************************************************************************************************************/

 

 

#define MAX_ENET_PACKET_SIZE 256

#define QUEUE_SIZE 5

 

typedef struct EnetMsg{

int ID;

int n;

char mybuffer[MAX_ENET_PACKET_SIZE];

} EnetMsg;

 

#define MSG_SIZE sizeof (EnetMsg)

 

 

/********************************************************************************************************************************

*Main.c

***************************************************************************************************************************/

 

 

Enet_RX_Queue = xQueueCreate(QUEUE_SIZE, MSG_SIZE);

if(Enet_RX_Queue==NULL){

xil_printf("\n\rFailed to create Enet_RX_Queue");

}

Enet_TX_Queue = xQueueCreate(QUEUE_SIZE, MSG_SIZE);

if(Enet_TX_Queue==NULL){

xil_printf("\n\rFailed to create Enet_TX_Queue");

}

 

 

 

sys_thread_new("main_thrd", (void(*)(void*))main_thread, 0,

THREAD_STACKSIZE,

3);

 

 

xil_printf("\n\rStarting Task Schedulter");

 

vTaskStartScheduler();

 

0 Kudos
Observer carloscruz
Observer
3,162 Views
Registered: ‎06-21-2017

Re: Extending the LWIP Echo Server

Jump to solution

Dear Paul ,
I am working correctly with the ethernet communication under echo server and TFTP server.This option provides simple transfer capability from the memory file system resident on the ZC706 board. I have used my hdl project and this lwIP is working well. I also setup ZC706_IwIP design for ETHERNET in echo server using your code.

My FPGa is connected to an ADC and data are correctly captured and are shown via UART. I need to send data from FPGA to PC by Ethernet. I was trying to use echo server as when a packet is received, the lwIP could send other packet with the data captured from the ADC. Could it be possible?. Currently I have some error because the system reply only the same packet received.
I am wondering how could I execute my capture function  in order send the data obtained from the ADC under echo server. Could it be possible?. Do you have any suggestion?

Thanks in advance

0 Kudos
Contributor
Contributor
1,030 Views
Registered: ‎07-29-2018

Re: Extending the LWIP Echo Server

Jump to solution

Dear paul

i am Anil, i also using lwip echo server, can you please tell me which variables are responsible for receiving and transmitting the data ,

i think p->payload is responsible for receiving the data, but i am not able to find out which variable is transmitting the data.i am attaching one file please find in attachment , file contain sdk terminal results,

your help will be very helpful for me ...............

thanks

Anil 

0 Kudos