⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uip-doc.txt

📁 最新版IAR FOR ARM(EWARM)5.11中的代码例子
💻 TXT
📖 第 1 页 / 共 4 页
字号:
}
\endcode

The configuration for the application:

\code
#define UIP_APPCALL       example2_app
#define UIP_APPSTATE_SIZE sizeof(struct example2_state)
\endcode

\subsection example3 Differentiating Between Applications

If the system should run multiple applications, one technique to
differentiate between them is to use the TCP port number of either the
remote end or the local end of the connection. The example below shows
how the two examples above can be combined into one application.

\code
void example3_init(void) {
   example1_init();
   example2_init();   
}

void example3_app(void) {
   switch(uip_conn->lport) {
   case HTONS(1234):
      example1_app();
      break;
   case HTONS(2345):
      example2_app();
      break;
   }
}
\endcode

\subsection example4 Utilizing TCP Flow Control

This example shows a simple application that connects to a host, sends
an HTTP request for a file and downloads it to a slow device such a
disk drive. This shows how to use the flow control functions of uIP.

\code
void example4_init(void) {
   u16_t ipaddr[2];
   uip_ipaddr(ipaddr, 192,168,0,1);
   uip_connect(ipaddr, HTONS(80));
}

void example4_app(void) {
   if(uip_connected() || uip_rexmit()) {
      uip_send("GET /file HTTP/1.0\r\nServer:192.186.0.1\r\n\r\n",
               48);
      return;
   }

   if(uip_newdata()) {
      device_enqueue(uip_appdata, uip_datalen());
      if(device_queue_full()) {
         uip_stop();
      }
   }

   if(uip_poll() && uip_stopped()) {
      if(!device_queue_full()) {
         uip_restart();
      }
   }
}
\endcode

When the connection has been established, an HTTP request is sent to
the server. Since this is the only data that is sent, the application
knows that if it needs to retransmit any data, it is that request that
should be retransmitted. It is therefore possible to combine these two
events as is done in the example.

When the application receives new data from the remote host, it sends
this data to the device by using the function device_enqueue(). It is
important to note that this example assumes that this function copies
the data into its own buffers. The data in the uip_appdata buffer will
be overwritten by the next incoming packet.

If the device's queue is full, the application stops the data from the
remote host by calling the uIP function uip_stop(). The application
can then be sure that it will not receive any new data until
uip_restart() is called. The application polling event is used to
check if the device's queue is no longer full and if so, the data flow
is restarted with uip_restart().

\subsection example5 A Simple Web Server

This example shows a very simple file server application that listens
to two ports and uses the port number to determine which file to
send. If the files are properly formatted, this simple application can
be used as a web server with static pages. The implementation follows.

\code
struct example5_state {
   char *dataptr;
   unsigned int dataleft;
};

void example5_init(void) {
   uip_listen(HTONS(80));
   uip_listen(HTONS(81));
}

void example5_app(void) {
   struct example5_state *s;
   s = (struct example5_state)uip_conn->appstate;
   
   if(uip_connected()) {
      switch(uip_conn->lport) {
      case HTONS(80):
         s->dataptr = data_port_80;
         s->dataleft = datalen_port_80;
         break;
      case HTONS(81):
         s->dataptr = data_port_81;
         s->dataleft = datalen_port_81;
         break;
      }
      uip_send(s->dataptr, s->dataleft);
      return;      
   }

   if(uip_acked()) {
      if(s->dataleft < uip_mss()) {
         uip_close();
         return;
      }
      s->dataptr += uip_conn->len;
      s->dataleft -= uip_conn->len;
      uip_send(s->dataptr, s->dataleft);      
   }
}
\endcode

The application state consists of a pointer to the data that should be
sent and the size of the data that is left to send. When a remote host
connects to the application, the local port number is used to
determine which file to send. The first chunk of data is sent using
uip_send(). uIP makes sure that no more than MSS bytes of data is
actually sent, even though s->dataleft may be larger than the MSS. 

The application is driven by incoming acknowledgments. When data has
been acknowledged, new data can be sent. If there is no more data to
send, the connection is closed using uip_close().

\subsection example6 Structured Application Program Design

When writing larger programs using uIP it is useful to be able to
utilize the uIP API in a structured way. The following example
provides a structured design that has showed itself to be useful for
writing larger protocol implementations than the previous examples
showed here. The program is divided into an uIP event handler function
that calls seven application handler functions that process new data,
act on acknowledged data, send new data, deal with connection
establishment or closure events and handle errors. The functions are
called newdata(), acked(), senddata(), connected(), closed(),
aborted(), and timedout(), and needs to be written specifically for
the protocol that is being implemented.

The uIP event handler function is shown below.

\code
void example6_app(void) {
  if(uip_aborted()) {
    aborted();
  }
  if(uip_timedout()) {
    timedout();
  }
  if(uip_closed()) {
    closed();
  }
  if(uip_connected()) {
    connected();
  }
  if(uip_acked()) {
    acked();
  }
  if(uip_newdata()) {
    newdata();
  }
  if(uip_rexmit() ||
     uip_newdata() ||
     uip_acked() ||
     uip_connected() ||
     uip_poll()) {
    senddata();
  }
}
\endcode

The function starts with dealing with any error conditions that might
have happened by checking if uip_aborted() or uip_timedout() are
true. If so, the appropriate error function is called. Also, if the
connection has been closed, the closed() function is called to the it
deal with the event.

Next, the function checks if the connection has just been established
by checking if uip_connected() is true. The connected() function is
called and is supposed to do whatever needs to be done when the
connection is established, such as intializing the application state
for the connection. Since it may be the case that data should be sent
out, the senddata() function is called to deal with the outgoing data.

The following very simple application serves as an example of how the
application handler functions might look. This application simply
waits for any data to arrive on the connection, and responds to the
data by sending out the message "Hello world!". To illustrate how to
develop an application state machine, this message is sent in two
parts, first the "Hello" part and then the "world!" part.

\code
#define STATE_WAITING 0
#define STATE_HELLO   1
#define STATE_WORLD   2

struct example6_state {
  u8_t state;
  char *textptr;
  int  textlen;
};

static void aborted(void) {}
static void timedout(void) {}
static void closed(void) {}

static void connected(void) {
  struct example6_state *s = (struct example6_state *)uip_conn->appstate;

  s->state   = STATE_WAITING;
  s->textlen = 0;
}

static void newdata(void) {
  struct example6_state *s = (struct example6_state *)uip_conn->appstate;

  if(s->state == STATE_WAITING) {
    s->state   = STATE_HELLO;
    s->textptr = "Hello ";
    s->textlen = 6;
  }
}

static void acked(void) {
  struct example6_state *s = (struct example6_state *)uip_conn->appstate;
  
  s->textlen -= uip_conn->len;
  s->textptr += uip_conn->len;
  if(s->textlen == 0) {
    switch(s->state) {
    case STATE_HELLO:
      s->state   = STATE_WORLD;
      s->textptr = "world!\n";
      s->textlen = 7;
      break;
    case STATE_WORLD:
      uip_close();
      break;
    }
  }
}

static void senddata(void) {
  struct example6_state *s = (struct example6_state *)uip_conn->appstate;

  if(s->textlen > 0) {
    uip_send(s->textptr, s->textlen);
  }
}
\endcode

The application state consists of a "state" variable, a "textptr"
pointer to a text message and the "textlen" length of the text
message. The "state" variable can be either "STATE_WAITING", meaning
that the application is waiting for data to arrive from the network,
"STATE_HELLO", in which the application is sending the "Hello" part of
the message, or "STATE_WORLD", in which the application is sending the
"world!" message. 

The application does not handle errors or connection closing events,
and therefore the aborted(), timedout() and closed() functions are
implemented as empty functions.

The connected() function will be called when a connection has been
established, and in this case sets the "state" variable to be
"STATE_WAITING" and the "textlen" variable to be zero, indicating that
there is no message to be sent out.

When new data arrives from the network, the newdata() function will be
called by the event handler function. The newdata() function will
check if the connection is in the "STATE_WAITING" state, and if so
switches to the "STATE_HELLO" state and registers a 6 byte long "Hello

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -