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

📄 uip-doc.txt

📁 最新版IAR FOR ARM(EWARM)5.11中的代码例子
💻 TXT
📖 第 1 页 / 共 4 页
字号:
the application does not necessarily increase because it takes an
active part in doing retransmissions.

\subsubsection appevents Application Events

The application must be implemented as a C function, UIP_APPCALL(),
that uIP calls whenever an event occurs. Each event has a corresponding
test function that is used to distinguish between different
events. The functions are implemented as C macros that will evaluate
to either zero or non-zero. Note that certain events can happen in
conjunction with each other (i.e., new data can arrive at the same
time as data is acknowledged).

\subsubsection connstate The Connection Pointer

When the application is called by uIP, the global variable uip_conn is
set to point to the uip_conn structure for the connection that
currently is handled, and is called the "current connection". The
fields in the uip_conn structure for the current connection can be
used, e.g., to distinguish between different services, or to check to
which IP address the connection is connected. One typical use would be
to inspect the uip_conn->lport (the local TCP port number) to decide
which service the connection should provide. For instance, an
application might decide to act as an HTTP server if the value of
uip_conn->lport is equal to 80 and act as a TELNET server if the value
is 23. 

\subsubsection recvdata Receiving Data

If the uIP test function uip_newdata() is non-zero, the remote host of
the connection has sent new data. The uip_appdata pointer point to the
actual data. The size of the data is obtained through the uIP function
uip_datalen(). The data is not buffered by uIP, but will be
overwritten after the application function returns, and the
application will therefor have to either act directly on the incoming
data, or by itself copy the incoming data into a buffer for later
processing.

\subsubsection senddata Sending Data

When sending data, uIP adjusts the length of the data sent by the
application according to the available buffer space and the current
TCP window advertised by the receiver. The amount of buffer space is
dictated by the memory configuration. It is therefore possible that
all data sent from the application does not arrive at the receiver,
and the application may use the uip_mss() function to see how much
data that actually will be sent by the stack.

The application sends data by using the uIP function uip_send(). The
uip_send() function takes two arguments; a pointer to the data to be
sent and the length of the data. If the application needs RAM space
for producing the actual data that should be sent, the packet buffer
(pointed to by the uip_appdata pointer) can be used for this purpose.

The application can send only one chunk of data at a time on a
connection and it is not possible to call uip_send() more than once
per application invocation; only the data from the last call will be
sent.

\subsubsection rexmitdata Retransmitting Data

Retransmissions are driven by the periodic TCP timer. Every time the
periodic timer is invoked, the retransmission timer for each
connection is decremented. If the timer reaches zero, a retransmission
should be made. As uIP does not keep track of packet contents after they have
been sent by the device driver, uIP requires that the
application takes an active part in performing the
retransmission. When uIP decides that a segment should be
retransmitted, the application function is called with the
uip_rexmit() flag set, indicating that a retransmission is
required.

The application must check the uip_rexmit() flag and produce the same
data that was previously sent. From the application's standpoint,
performing a retransmission is not different from how the data
originally was sent. Therefor, the application can be written in such
a way that the same code is used both for sending data and
retransmitting data. Also, it is important to note that even though
the actual retransmission operation is carried out by the application,
it is the responsibility of the stack to know when the retransmission
should be made. Thus the complexity of the application does not
necessarily increase because it takes an active part in doing
retransmissions.

\subsubsection closing Closing Connections

The application closes the current connection by calling the
uip_close() during an application call. This will cause the connection
to be cleanly closed. In order to indicate a fatal error, the
application might want to abort the connection and does so by calling
the uip_abort() function.

If the connection has been closed by the remote end, the test function
uip_closed() is true. The application may then do any necessary
cleanups.

\subsubsection errors Reporting Errors

There are two fatal errors that can happen to a connection, either
that the connection was aborted by the remote host, or that the
connection retransmitted the last data too many times and has been
aborted. uIP reports this by calling the application function. The
application can use the two test functions uip_aborted() and
uip_timedout() to test for those error conditions.

\subsubsection polling Polling

When a connection is idle, uIP polls the application every time the
periodic timer fires. The application uses the test function
uip_poll() to check if it is being polled by uIP.

The polling event has two purposes. The first is to let the
application periodically know that a connection is idle, which allows
the application to close connections that have been idle for too
long. The other purpose is to let the application send new data that
has been produced. The application can only send data when invoked by
uIP, and therefore the poll event is the only way to send data on an
otherwise idle connection.

\subsubsection listen Listening Ports

uIP maintains a list of listening TCP ports. A new port is opened for
listening with the uip_listen() function. When a connection request
arrives on a listening port, uIP creates a new connection and calls
the application function. The test function uip_connected() is true if
the application was invoked because a new connection was created.

The application can check the lport field in the uip_conn structure to
check to which port the new connection was connected.

\subsubsection connect Opening Connections

New connections can be opened from within
uIP by the function uip_connect(). This function
allocates a new connection and sets a flag in the connection state
which will open a TCP connection to the specified IP address and port
the next time the connection is polled by uIP. The uip_connect()
function returns
a pointer to the uip_conn structure for the new
connection. If there are no free connection slots, the function
returns NULL. 

The function uip_ipaddr() may be used to pack an IP address into the
two element 16-bit array used by uIP to represent IP addresses.

Two examples of usage are shown below. The first example shows how to
open a connection to TCP port 8080 of the remote end of the current
connection. If there are not enough TCP connection slots to allow a
new connection to be opened, the uip_connect() function returns NULL
and the current connection is aborted by uip_abort(). 

\code
void connect_example1_app(void) {
   if(uip_connect(uip_conn->ripaddr, HTONS(8080)) == NULL) {
      uip_abort();
   }
}   
\endcode

The second example shows how to open a new connection to a specific IP
address. No error checks are made in this example.

\code
void connect_example2(void) {
   u16_t ipaddr[2];

   uip_ipaddr(ipaddr, 192,168,0,1);
   uip_connect(ipaddr, HTONS(8080));
}
\endcode

\section examples Examples

This section presents a number of very simple uIP applications. The
uIP code distribution contains several more complex applications.

\subsection example1 A Very Simple Application

This first example shows a very simple application. The application
listens for incoming connections on port 1234. When a connection has
been established, the application replies to all data sent to it by
saying "ok"

The implementation of this application is shown below. The application
is initialized with the function called example1_init() and the uIP
callback function is called example1_app(). For this application, the
configuration variable UIP_APPCALL should be defined to be
example1_app().

\code
void example1_init(void) {
   uip_listen(HTONS(1234));
}

void example1_app(void) {
   if(uip_newdata() || uip_rexmit()) {
      uip_send("ok\n", 3);
   }
}
\endcode

The initialization function calls the uIP function uip_listen() to
register a listening port. The actual application function
example1_app() uses the test functions uip_newdata() and uip_rexmit()
to determine why it was called. If the application was called because
the remote end has sent it data, it responds with an "ok". If the
application function was called because data was lost in the network
and has to be retransmitted, it also sends an "ok".  Note that this
example actually shows a complete uIP application. It is not required
for an application to deal with all types of events such as
uip_connected() or uip_timedout(). 

\subsection example2 A More Advanced Application

This second example is slightly more advanced than the previous one,
and shows how the application state field in the uip_conn structure is
used.

This application is similar to the first application in that it
listens to a port for incoming connections and responds to data sent
to it with a single "ok". The big difference is that this application
prints out a welcoming "Welcome!" message when the connection has been
established.

This seemingly small change of operation makes a big difference in how
the application is implemented. The reason for the increase in
complexity is that if data should be lost in the network, the
application must know what data to retransmit. If the "Welcome!"
message was lost, the application must retransmit the welcome and if
one of the "ok" messages is lost, the application must send a new
"ok".

The application knows that as long as the "Welcome!" message has not
been acknowledged by the remote host, it might have been dropped in
the network. But once the remote host has sent an acknowledgment
back, the application can be sure that the welcome has been received
and knows that any lost data must be an "ok" message. Thus the
application can be in either of two states: either in the WELCOME-SENT
state where the "Welcome!" has been sent but not acknowledged, or in
the WELCOME-ACKED state where the "Welcome!" has been acknowledged.

When a remote host connects to the application, the application sends
the "Welcome!" message and sets it's state to WELCOME-SENT. When the
welcome message is acknowledged, the application moves to the
WELCOME-ACKED state. If the application receives any new data from the
remote host, it responds by sending an "ok" back.

If the application is requested to retransmit the last message, it
looks at in which state the application is. If the application is in
the WELCOME-SENT state, it sends a "Welcome!"  message since it
knows that the previous welcome message hasn't been acknowledged. If
the application is in the WELCOME-ACKED state, it knows that the last
message was an "ok" message and sends such a message.

The implementation of this application is seen below. This
configuration settings for the application is follows after its
implementation.

\code
struct example2_state {
   enum {WELCOME_SENT, WELCOME_ACKED} state;
};

void example2_init(void) {
   uip_listen(HTONS(2345));
}

void example2_app(void) {
   struct example2_state *s;

   s = (struct example2_state *)uip_conn->appstate;
   
   if(uip_connected()) {
      s->state = WELCOME_SENT;
      uip_send("Welcome!\n", 9);
      return;
   } 

   if(uip_acked() && s->state == WELCOME_SENT) {
      s->state = WELCOME_ACKED;
   }

   if(uip_newdata()) {
      uip_send("ok\n", 3);
   }

   if(uip_rexmit()) {
      switch(s->state) {
      case WELCOME_SENT:
         uip_send("Welcome!\n", 9);
         break;
      case WELCOME_ACKED:
         uip_send("ok\n", 3);
         break;
      }
   }

⌨️ 快捷键说明

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