lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-users] How to build a simple TCP server and client which run on th


From: Antonio de Angelis
Subject: [lwip-users] How to build a simple TCP server and client which run on the same machine
Date: Tue, 08 Jul 2008 14:35:39 +0200
User-agent: Thunderbird 2.0.0.14 (Windows/20080421)

Hi all,
I'm using the win32 port and I'm trying to build a simple TCP server and a TCP client on the same machine as two separate processes (using the same ethernet adapter). The client connects to the server, sends a messagge (i.e., "Hello") waits for the ACK and closes its connection. The server waits for the client to connect, then when it receives the incoming message, it prints the message on screen and closes its connection. I'm using the NO_SYS = 1 option and the raw API. I've created the server, and it seems to function: infact if I connect on the specified port simply using a web browser(i.e. http://192.168.1.200:8000) the server process prints correctly the first string associated with the GET request from the browser. Here it is the code:

#include "lwip/tcp.h"

static err_t server_accept(void *arg, struct tcp_pcb *pcb, err_t err);
static err_t server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
static err_t server_poll(void *arg, struct tcp_pcb *pcb);
static err_t server_err(void *arg, err_t err);

void my_server_init(void)
{
   struct tcp_pcb *pcb;

   pcb = tcp_new();
   tcp_bind(pcb, IP_ADDR_ANY, 8000); //server port for incoming connection
   pcb = tcp_listen(pcb);
   tcp_accept(pcb, server_accept);
}

static void server_close(struct tcp_pcb *pcb)
{
   tcp_arg(pcb, NULL);
   tcp_sent(pcb, NULL);
   tcp_recv(pcb, NULL);
   tcp_close(pcb);

   printf("\nserver_close(): Closing...\n");
}

static err_t server_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
   LWIP_UNUSED_ARG(arg);
   LWIP_UNUSED_ARG(err);

   tcp_setprio(pcb, TCP_PRIO_MIN);

   tcp_arg(pcb, NULL);

   tcp_recv(pcb, server_recv);

   tcp_err(pcb, server_err);

tcp_poll(pcb, server_poll, 4); //every two seconds of inactivity of the TCP connection

   tcp_accepted(pcb);
printf("\nserver_accept(): Accepting incoming connection on server...\n"); return ERR_OK;
}

static err_t server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
   char *string;
   int length;
   LWIP_UNUSED_ARG(arg);

   if (err == ERR_OK && p != NULL)
   {
       tcp_recved(pcb, p->tot_len);

       string = p->payload;
       length = strlen(string);
printf("\nserver_recv(): Incoming string is %s\n", string);
       printf("\nserver_recv(): String length is %d byte\n", length);
       printf("server_recv(): pbuf->len is %d byte\n", p->len);
       printf("server_recv(): pbuf->tot_len is %d byte\n", p->tot_len);
       printf("server_recv(): pbuf->next is %d\n", p->next);

       pbuf_free(p);
       server_close(pcb);
   }
   else
   {
       printf("\nserver_recv(): Errors-> ");
       if (err != ERR_OK)
printf("1) Connection is not on ERR_OK state, but in %d state->\n", err);
       if (p == NULL)
           printf("2) Pbuf pointer p is a NULL pointer->\n ");
       printf("server_recv(): Closing server-side connection...");

       pbuf_free(p);
       server_close(pcb);
   }

   return ERR_OK;
}

static err_t server_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
   LWIP_UNUSED_ARG(len);
   LWIP_UNUSED_ARG(arg);

printf("\nserver_sent(): Correctly ACK'ed, closing server-side connection...\n");
   server_close(pcb);

   return ERR_OK;
}

static err_t server_poll(void *arg, struct tcp_pcb *pcb)
{
   static int counter = 1;
   LWIP_UNUSED_ARG(arg);
   LWIP_UNUSED_ARG(pcb);

   printf("\nserver_poll(): Call number %d\n", counter++);

   return ERR_OK;
}

static err_t server_err(void *arg, err_t err)
{
   LWIP_UNUSED_ARG(arg);
   LWIP_UNUSED_ARG(err);

   printf("\nserver_err(): Fatal error, exiting...\n");

   return ERR_OK;
}

Now i'm trying to create the client. But the communication between the processes doesn't work: the client send the SYN segment but never receives an answer, and the server never receives the connection request from the client. I've built the server process giving it the address 192.168.1.200 and the client process with 192.168.1.201. They are separate processes on the same machine but they use the same network adapter. Here it is the code for the client:

static err_t client_sent(void *arg, struct tcp_pcb *pcb, u16_t len);
static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err);

void my_client_init(void)
{
   struct tcp_pcb *pcb;
   struct ip_addr dest;
   err_t ret_val;
   IP4_ADDR(&dest, 192, 168, 1, 200);

   pcb = tcp_new();
   tcp_bind(pcb, IP_ADDR_ANY, 7000); //client port for outcoming connection
   tcp_arg(pcb, NULL);
ret_val = tcp_connect(pcb, &dest, 8000, client_connected); //server port for incoming connection
   if (ret_val != ERR_OK)
printf("\tcp_connect(): Errors on return value, returned value is %d\n", ret_val);
}

static void client_close(struct tcp_pcb *pcb)
{
   tcp_arg(pcb, NULL);
   tcp_sent(pcb, NULL);
   tcp_close(pcb);

   printf("\nclient_close(): Closing...\n");
}

static err_t client_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
   char *string = "Hello!";
   LWIP_UNUSED_ARG(arg);

   if (err != ERR_OK)
printf("\nclient_connected(): err argument not set to ERR_OK, but is value is %d\n", err);

   else
   {
       tcp_sent(pcb, client_sent);
       tcp_write(pcb, string, sizeof(string), 0);
   }

   return err;
}

static err_t client_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
   LWIP_UNUSED_ARG(arg);

   printf("\nclient_sent(): Number of bytes ACK'ed is %d", len);

   client_close(pcb);

   return ERR_OK;
}

I'm using the test.c file "model" to build my applications: I've removed from the test application all the code which I don't need and then I've introduced the source code written for my applications. I use the same test.c for both the client and server, compiling it with my_client_init(); or my_server_init() for the client or the server. So the code for test.c file (containing the main()) is this:

/* C runtime includes */
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <string.h>
#include <conio.h>

/* lwIP core includes */
#include "lwip/opt.h"

#include "lwip/init.h"

#include "lwip/tcp.h"

/* lwIP netif includes */
#include "netif/etharp.h"

/* applications includes */

/*
#include "server.h"
#include "client.h"
*/
void my_server_init(void);
void my_client_init(void);

/* NO_SYS == 1: we need information about the timer intervals: */
#include "lwip/ip_frag.h"
#include "lwip/igmp.h"

/* ethernet layer include */
#include "pktif.h"

/* include the port-dependent configuration */
#include "lwipcfg_msvc.h"

/* port-defined functions used for timer execution, defined in sys_arch.c */
void sys_init_timing();
u32_t sys_now();

/* globales variables for netifs */
/* THE ethernet interface */
struct netif netif;

/* special functions used for NO_SYS==1 only */
typedef struct _timers_infos
{
   int timer;
   int timer_interval;
   void (*timer_func)(void);
} timers_infos;

static timers_infos timers_table[] =
{
   { 0, TCP_FAST_INTERVAL,       tcp_fasttmr},
   { 0, TCP_SLOW_INTERVAL,       tcp_slowtmr},
   { 0, ARP_TMR_INTERVAL,        etharp_tmr},
   { 0, IGMP_TMR_INTERVAL,       igmp_tmr},
   { 0, IP_TMR_INTERVAL,         ip_reass_tmr},
};

/* get the current time and see if any timer has expired */
static void timers_update()
{
   /* static variables for timer execution, initialized to zero! */
   static int last_time;
int cur_time, time_diff, idxtimer;

   cur_time = sys_now();
   time_diff = cur_time - last_time;

   /* the '> 0' is an easy wrap-around check: the big gap at
    * the wraparound step is simply ignored... */
   if (time_diff > 0)
   {
       last_time = cur_time;
for( idxtimer=0; idxtimer<(sizeof(timers_table)/sizeof(timers_infos)); idxtimer++)
       {
           timers_table[idxtimer].timer += time_diff;

if (timers_table[idxtimer].timer > timers_table[idxtimer].timer_interval)
           {
               timers_table[idxtimer].timer_func();
timers_table[idxtimer].timer -= timers_table[idxtimer].timer_interval;
           }
       }
   }
}

void status_callback(struct netif *netif)
{
   if (netif_is_up(netif))
{ printf("status_callback==UP, local interface IP is %s\n", inet_ntoa(*(struct in_addr*)&(netif->ip_addr)));
   }
   else
   {
       printf("status_callback==DOWN\n");
   }
}

void link_callback(struct netif *netif)
{
   if (netif_is_link_up(netif))
   {
       printf("link_callback==UP\n");
   }
   else
   {
       printf("link_callback==DOWN\n");
   }
}

/* This function initializes all network interfaces */
static void msvc_netif_init()
{
   struct ip_addr ipaddr, netmask, gw;

   LWIP_PORT_INIT_GW(&gw);
   LWIP_PORT_INIT_IPADDR(&ipaddr);
   LWIP_PORT_INIT_NETMASK(&netmask);
printf("Starting lwIP, local interface IP is %s\n", inet_ntoa(*(struct in_addr*)&ipaddr));

netif_set_default(netif_add(&netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input));

   netif_set_status_callback(&netif, status_callback);

   netif_set_link_callback(&netif, link_callback);

   netif_set_up(&netif);
}

void main_loop()
{
   /* initialize lwIP stack, network interfaces and application */
   sys_init_timing();
   lwip_init();
/* init network interfaces */
   msvc_netif_init();

   /* init application */
//my_server_init(); /* My Server */

   my_client_init(); /* My Client */

   /* MAIN LOOP for driver update (and timers if NO_SYS) */
   while (!_kbhit())
   {
       /* handle timers (already done in tcpip.c when NO_SYS=0) */
       timers_update();

       /* check for packets and link status*/
       ethernetif_poll(&netif);

       /* check for loopback packets on all netifs */
       netif_poll_all();
   }

   /* release the pcap library... */
   ethernetif_shutdown(&netif);
}

int main(void)
{
   /* no stdio-buffering, please! */
   setvbuf(stdout, NULL,_IONBF, 0);

   main_loop();

   return 0;
}

I hope that someone can help me, I don't know why the communication doesn't work, I can't understand! Thank you Bye!

Antonio de Angelis









reply via email to

[Prev in Thread] Current Thread [Next in Thread]