7

I am using FreeRTOS + LwIP to develop a Ethernet based bedside nurse call device. After reading some examples and document, I want to use the LwIP's netconn API to send and receive data under TCP, because I am not familiar with the BSD style API and the raw API may be difficult.

I know the netconn_accept() function will block the process until a connection request from a remote host arrived, and the netconn_recv() function will also block the process while waiting for data to arrive...both of these functions will block the process, it is good for a server receiving data, however, my device also need to act as a client which need to trigger a 'call' to the nurse center when the patient press a button. So how can it initiates to send a TCP packet while it is also waiting a connection(blocking the process) from the remote host?

I need to send TCP because I have to use SIP(Session Initiation Protocol) to initiate a call, the it should be reliable because it is a medical device. Thank you very much


@Kyle Heironimus , @werewindle I add you to my question because I know you have experience on LwIP, hope that will not make you inconvenience and hope that you can help, thank you.

eepty
  • 716
  • 3
  • 10
  • 28
  • As I am using FreeRTOS, today I tried to use two threads, one as a server waiting for connection, another one as a client to open a TCP connection when needed. The server thread is doing well, but at the client side, it always return error when I call `netconn_connect()`...I tried to use same and different port for the server and client, but still failed – eepty Apr 23 '12 at 17:49
  • please help me with this problem, https://stackoverflow.com/questions/51112786/ethernet-unplugged-state-verification-by-netconn-api – Nitin Rawal Jun 30 '18 at 07:35

1 Answers1

7

You cannot send data to a remote host before it has initiated a connection. That just doesn't make any sense. My question is: do you want your device connect to the remote host, or do you want the remote host initiate a connection to your device?

Right now you're using netconn_accept in your device - that means that you are waiting for the remote host to initiate a connection to your device before your device can signal the remote host. This is entirely expected behavior for the code you've written yet you seem concerned about this. Is this not your intention? If not, why did you code it that way? The other alternative is to have your device initiate the connection to the remote host. There's an example of that use of netconns here. Of course, this involves changes to the other device in your system as well.

So the moral of that story is that you can't send any data when no connection is present, and you're waiting for a connection before you send data. You don't want to wait for the connection, so you have to change your software to initiate the connection rather than wait for the other side to initiate it.

Another problem you might run into is that you want to be able to send and receive data on the same connection at the same time. Most examples I saw for lwip involves blocking calls waiting for data, then reacting to that data by transmitting something back. Sometimes you want to transmit something back without receiving something first. I can help with that too.

This is what worked for me when I created a listening netconn connection.

First, you have to enable timeouts by setting:

#define LWIP_SO_RCVTIMEO 1

Then you have to set up your netconn similarly to this:

pxTCPListener = netconn_new (NETCONN_TCP);

netconn_bind (pxTCPListener, NULL, 23);

netconn_listen (pxTCPListener);

pxNewConnection = netconn_accept (pxTCPListener); //This blocks until connection is accepted

//This is the important line!

pxNewConnection->recv_timeout = 10; //note This is millseconds - lwip works in ms

//This loops until the connection is closed

while(!ERR_IS_FATAL(pxNewConnection->err)) { //Fatal errors include connections being closed, reset, aborted, etc

//This netconn_recv call will now wait 10ms for any new data, then return

if ((pxRxBuffer = netconn_recv (pxNewConnection)) != NULL) {

//Handle received data

}

//Here, do any transmits you want

} //End of while loop from above

That code will allow you to do transmits and receives at the same time without worrying about blocking.

Stephen Friederichs
  • 1,029
  • 6
  • 12
  • Thank you Stephen, the nurse call device will act as a server, waiting for connection, – eepty Apr 26 '12 at 17:03
  • Yeah... why is that? It seems like the call device should initiate the connection to a server since the action that triggers all of this is someone pushing a button on it rather than wait for something to connect to it so it can tell it a button was pressed. – Stephen Friederichs Apr 26 '12 at 17:20
  • Thank you very much for you detail answer Stephen. The device is like a phone, it waits for connection normally, act as a server, but if a person press a button on it, it'll initiate a connection, act as a client. These two situations will not exist at the same time, and both situations involve receive and transmit. Recently I've succeeded to implement these two tasks separately..after a long reading...I separated them in two different tasks in FreeRTOS, enabling one task will block another. I've tested each task separately but not tested them running together...I'm new to RTOS but I'll try – eepty Apr 26 '12 at 18:02
  • Hey Stephen, your line" `while(!ERR_IS_FATAL(pxNewConnection->err))` help me a lot. Since althought I can receive and send before, but I need to connect and disconnect the TCP connection for each receive, if not the program will hang. Thank you again – eepty Apr 29 '12 at 08:29
  • Yeah that was a good one for me too. Not many examples out there on full duplex communication. – Stephen Friederichs Apr 29 '12 at 13:18