📄 uip-doc.txt
字号:
the application does not necessarily increase because it takes anactive part in doing retransmissions.\subsubsection appevents Application EventsThe application must be implemented as a C function, UIP_APPCALL(),that uIP calls whenever an event occurs. Each event has a correspondingtest function that is used to distinguish between differentevents. The functions are implemented as C macros that will evaluateto either zero or non-zero. Note that certain events can happen inconjunction with each other (i.e., new data can arrive at the sametime as data is acknowledged).\subsubsection connstate The Connection PointerWhen the application is called by uIP, the global variable uip_conn isset to point to the uip_conn structure for the connection thatcurrently is handled, and is called the "current connection". Thefields in the uip_conn structure for the current connection can beused, e.g., to distinguish between different services, or to check towhich IP address the connection is connected. One typical use would beto inspect the uip_conn->lport (the local TCP port number) to decidewhich service the connection should provide. For instance, anapplication might decide to act as an HTTP server if the value ofuip_conn->lport is equal to 80 and act as a TELNET server if the valueis 23. \subsubsection recvdata Receiving DataIf the uIP test function uip_newdata() is non-zero, the remote host ofthe connection has sent new data. The uip_appdata pointer point to theactual data. The size of the data is obtained through the uIP functionuip_datalen(). The data is not buffered by uIP, but will beoverwritten after the application function returns, and theapplication will therefor have to either act directly on the incomingdata, or by itself copy the incoming data into a buffer for laterprocessing.\subsubsection senddata Sending DataWhen sending data, uIP adjusts the length of the data sent by theapplication according to the available buffer space and the currentTCP window advertised by the receiver. The amount of buffer space isdictated by the memory configuration. It is therefore possible thatall data sent from the application does not arrive at the receiver,and the application may use the uip_mss() function to see how muchdata that actually will be sent by the stack.The application sends data by using the uIP function uip_send(). Theuip_send() function takes two arguments; a pointer to the data to besent and the length of the data. If the application needs RAM spacefor 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 aconnection and it is not possible to call uip_send() more than onceper application invocation; only the data from the last call will besent.\subsubsection rexmitdata Retransmitting DataRetransmissions are driven by the periodic TCP timer. Every time theperiodic timer is invoked, the retransmission timer for eachconnection is decremented. If the timer reaches zero, a retransmissionshould be made. As uIP does not keep track of packet contents after they havebeen sent by the device driver, uIP requires that theapplication takes an active part in performing theretransmission. When uIP decides that a segment should beretransmitted, the application function is called with theuip_rexmit() flag set, indicating that a retransmission isrequired.The application must check the uip_rexmit() flag and produce the samedata that was previously sent. From the application's standpoint,performing a retransmission is not different from how the dataoriginally was sent. Therefor, the application can be written in sucha way that the same code is used both for sending data andretransmitting data. Also, it is important to note that even thoughthe actual retransmission operation is carried out by the application,it is the responsibility of the stack to know when the retransmissionshould be made. Thus the complexity of the application does notnecessarily increase because it takes an active part in doingretransmissions.\subsubsection closing Closing ConnectionsThe application closes the current connection by calling theuip_close() during an application call. This will cause the connectionto be cleanly closed. In order to indicate a fatal error, theapplication might want to abort the connection and does so by callingthe uip_abort() function.If the connection has been closed by the remote end, the test functionuip_closed() is true. The application may then do any necessarycleanups.\subsubsection errors Reporting ErrorsThere are two fatal errors that can happen to a connection, eitherthat the connection was aborted by the remote host, or that theconnection retransmitted the last data too many times and has beenaborted. uIP reports this by calling the application function. Theapplication can use the two test functions uip_aborted() anduip_timedout() to test for those error conditions.\subsubsection polling PollingWhen a connection is idle, uIP polls the application every time theperiodic timer fires. The application uses the test functionuip_poll() to check if it is being polled by uIP.The polling event has two purposes. The first is to let theapplication periodically know that a connection is idle, which allowsthe application to close connections that have been idle for toolong. The other purpose is to let the application send new data thathas been produced. The application can only send data when invoked byuIP, and therefore the poll event is the only way to send data on anotherwise idle connection.\subsubsection listen Listening PortsuIP maintains a list of listening TCP ports. A new port is opened forlistening with the uip_listen() function. When a connection requestarrives on a listening port, uIP creates a new connection and callsthe application function. The test function uip_connected() is true ifthe application was invoked because a new connection was created.The application can check the lport field in the uip_conn structure tocheck to which port the new connection was connected.\subsubsection connect Opening ConnectionsNew connections can be opened from withinuIP by the function uip_connect(). This functionallocates a new connection and sets a flag in the connection statewhich will open a TCP connection to the specified IP address and portthe next time the connection is polled by uIP. The uip_connect()function returnsa pointer to the uip_conn structure for the newconnection. If there are no free connection slots, the functionreturns NULL. The function uip_ipaddr() may be used to pack an IP address into thetwo element 16-bit array used by uIP to represent IP addresses.Two examples of usage are shown below. The first example shows how toopen a connection to TCP port 8080 of the remote end of the currentconnection. If there are not enough TCP connection slots to allow anew connection to be opened, the uip_connect() function returns NULLand the current connection is aborted by uip_abort(). \codevoid connect_example1_app(void) { if(uip_connect(uip_conn->ripaddr, HTONS(8080)) == NULL) { uip_abort(); }} \endcodeThe second example shows how to open a new connection to a specific IPaddress. No error checks are made in this example.\codevoid connect_example2(void) { u16_t ipaddr[2]; uip_ipaddr(ipaddr, 192,168,0,1); uip_connect(ipaddr, HTONS(8080));}\endcode\section examples ExamplesThis section presents a number of very simple uIP applications. TheuIP code distribution contains several more complex applications.\subsection example1 A Very Simple ApplicationThis first example shows a very simple application. The applicationlistens for incoming connections on port 1234. When a connection hasbeen established, the application replies to all data sent to it bysaying "ok"The implementation of this application is shown below. The applicationis initialized with the function called example1_init() and the uIPcallback function is called example1_app(). For this application, theconfiguration variable UIP_APPCALL should be defined to beexample1_app().\codevoid example1_init(void) { uip_listen(HTONS(1234));}void example1_app(void) { if(uip_newdata() || uip_rexmit()) { uip_send("ok\n", 3); }}\endcodeThe initialization function calls the uIP function uip_listen() toregister a listening port. The actual application functionexample1_app() uses the test functions uip_newdata() and uip_rexmit()to determine why it was called. If the application was called becausethe remote end has sent it data, it responds with an "ok". If theapplication function was called because data was lost in the networkand has to be retransmitted, it also sends an "ok". Note that thisexample actually shows a complete uIP application. It is not requiredfor an application to deal with all types of events such asuip_connected() or uip_timedout(). \subsection example2 A More Advanced ApplicationThis second example is slightly more advanced than the previous one,and shows how the application state field in the uip_conn structure isused.This application is similar to the first application in that itlistens to a port for incoming connections and responds to data sentto it with a single "ok". The big difference is that this applicationprints out a welcoming "Welcome!" message when the connection has beenestablished.This seemingly small change of operation makes a big difference in howthe application is implemented. The reason for the increase incomplexity is that if data should be lost in the network, theapplication must know what data to retransmit. If the "Welcome!"message was lost, the application must retransmit the welcome and ifone of the "ok" messages is lost, the application must send a new"ok".The application knows that as long as the "Welcome!" message has notbeen acknowledged by the remote host, it might have been dropped inthe network. But once the remote host has sent an acknowledgmentback, the application can be sure that the welcome has been receivedand knows that any lost data must be an "ok" message. Thus theapplication can be in either of two states: either in the WELCOME-SENTstate where the "Welcome!" has been sent but not acknowledged, or inthe WELCOME-ACKED state where the "Welcome!" has been acknowledged.When a remote host connects to the application, the application sendsthe "Welcome!" message and sets it's state to WELCOME-SENT. When thewelcome message is acknowledged, the application moves to theWELCOME-ACKED state. If the application receives any new data from theremote host, it responds by sending an "ok" back.If the application is requested to retransmit the last message, itlooks at in which state the application is. If the application is inthe WELCOME-SENT state, it sends a "Welcome!" message since itknows that the previous welcome message hasn't been acknowledged. Ifthe application is in the WELCOME-ACKED state, it knows that the lastmessage was an "ok" message and sends such a message.The implementation of this application is seen below. Thisconfiguration settings for the application is follows after itsimplementation.\codestruct 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 + -