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
_______________________________________________
lwip-users mailing list
lwip-users@nongnu.org
http://lists.nongnu.org/mailman/listinfo/lwip-users