Page 1 of 1

lwIP TCP client

Posted: Thu Apr 03, 2014 3:30 pm
by Jeroen3
I was looking for an example of an TCP client for lwIP, but all I could find were TCP web servers.
So I dived into lwIP to understand how to do this. Aside from noticing lwIP is a mess of half-defined functions, unclear preconditions and a lot of #ifdef settings. I managed to come up with this:

Code: Select all

#include "ch.h"
#include "hal.h"
#include "threads.h" // shared resources and semaphores
#include "chprintf.h"
#include "lwip/api.h"
#include <stdio.h>

#define cout ((BaseSequentialStream *) &SD2)

msg_t Thread2(void *arg);
WORKING_AREA(waThread2, 512);

msg_t Thread2(void *arg)
{
   // nested block to ensure cleanup of local variables since chThdExit() doesn't return!
   {
      // const for placement in ROM, static for pre-allocation in compiler instead of heap
      const systime_t t = 100;
      static uint32_t i=0;
      
      // Connection
      static struct netconn *conn;
      static ip_addr_t ip;   
      IP4_ADDR(&ip, 192,168,5,10);
      // Payload
      const char buf[] = "This is a test, system time is now ";
      static char send_cache[64];
      // Error checking
      static err_t err;
      
      // Name thread
      chRegSetThreadName("tcp_conn");
      
      // Forever, unless requested to terminate
      while (!chThdShouldTerminate()) {
         // Create new connection
         conn = netconn_new( NETCONN_TCP );
         // Suggest this local port (doesn't always work)
         netconn_bind(conn, IP_ADDR_ANY, 1234 );
         // Set timeout, otherwise netconn_write() won't fail
         netconn_set_sendtimeout(conn, 1000);
         // Connect to ip
         err = netconn_connect(conn, &ip, 1235 );
         // Verify connection
         if(err != ERR_OK){
            // Report failed
            chSemWait(&coutLock);
            chprintf(cout, "tcp could not connect\r\n");
            chSemSignal(&coutLock);
         }else{
            // Continously send a datastring with systime
            do{
               // Assemble datastring in cache
               uint32_t size = sprintf(send_cache,"%s%d\r\n", buf, chTimeNow());
               // Write cache to tcp, blocking without copy to lwip data
               err = netconn_write(conn, send_cache, size, NETCONN_NOCOPY);
               // Blink a led
               palTogglePad(GPIOD, GPIOD_LED4);
               // Report success
               chSemWait(&coutLock);
               chprintf(cout, "tcp %010d, %d\r\n", chTimeNow(), i++);
               chSemSignal(&coutLock);
               // Wait a while
               chThdSleepMilliseconds(t);
               // Check for success
            }while(err == ERR_OK && !chThdShouldTerminate());
               // report disconnect
               chSemWait(&coutLock);
               chprintf(cout, "tcp disconnected %d\r\n", netconn_err(conn));
               chSemSignal(&coutLock);
         }
         // Failed, close connection (probably caused by a disconnect or ignore by the server)
         netconn_close(conn);
         // Delete connection and start over
         netconn_delete(conn);      
         // Delay, otherwise the cout will flood (the pc cannot keep up)
         chThdSleepMilliseconds(1000);
      } // end of while
   } // end of block
   chThdExit(0);
   return 0;
}

I'm convinced this can serve as an example with at least some quality, please improve if you disagree.