Like Wikia on Facebook!
Lifestyle
Entertainment
Video Games
(last changed: June 16, 2011)
Contents
1 Initialization
2 TCP connection setup
2.1 Passive connection (Listen)2.2 Active connection 3 TCP connection functions 4 Sending TCP data 5 Receiving TCP data 6 Application polling
7 Closing and aborting connections 8 Miscellaneous TCP Functions
8.1 Nagle Algorithm 8.2 TCP Keepalive
9 Raw TCP Sample Sequence Diagrams
Initialization
lwip_init() must be called before any tcp functions are called.
v o i d t c p _t m r (v o i d )
After lwip_init() is called, you must call tcp_tmr() every TCP_TMR_INTERVAL milliseconds (default is 250 milliseconds).
TCP connection setup
A TCP connection is identified by a protocol control block (PCB). There are two ways to set up a connection.
Passive connection (Listen)
1. Call tcp_new to create a pcb.
2. Optionally call tcp_arg to associate an application-specific value with the pcb.
3. Call tcp_bind to specify the local IP address and port.
4. Call tcp_listen or tcp_listen_with_backlog.
5. Call tcp_accept to specify the function to be called when a new connection arrives. Note that there is no possibility of a socket being accepted before specifying the callback, because this is all run on the tcpip_thread.
Active connection
1. Call tcp_new to create a pcb.
2. Optionally call tcp_arg to associate an application-specific value with the pcb.
3. Optionally call tcp_bind to specify the local IP address and port.
4. Call tcp_connect.
TCP connection functions
s t r u c t t c p _p c b * t c p _n e w (v o i d )
Creates a new connection control block (PCB). The connection is initially in the "closed" state. If memory is not available for creating the new pcb, NULL is returned.
v o i d t c p _a r g (s t r u c t t c p _p c b * p c b , v o i d * a r g )
The "pcb" argument specifies a TCP connection control block, and the "arg" argument is the argument that will be passed to all the callbacks for that connection. This argument can be used by the application for any purpose.
e r r _t t c p _b i n d (s t r u c t t c p _p c b * p c b , s t r u c t i p _a d d r * i p a d d r , u 16_t p o r t )
Binds the pcb to a local IP address and port number. The IP address can be specified as IP_ADDR_ANY in order to bind the connection to all local IP addresses. If the port is specified as zero, the function selects an available port. The connection must be in the "closed" state.
If another connection is bound to the same port, the function will return ERR_USE, otherwise ERR_OK is returned.
tcpip协议pdfs t r u c t t c p _p c b * t c p _l i s t e n (s t r u c t t c p _p c b * p c b )
The "pcb" parameter specifies a connection, which must be in the "closed" state and must have been bound to a local port with the tcp_bind() function. This functions sets up the local port to listen for incoming connections.
The tcp_listen() function returns a new connection control block, and the one passed as an argument to the function will be deallocated. The reason for this behavior is that less memory is needed for a connection that is listening, so tcp_listen() will reclaim the memory needed for the original connection and allocate a new smaller memory block for the listening connection.
Raw/TCP
After calling tcp_listen(), you must call tcp_accept(). Until you do so, incoming connections for this port will be aborted.
tcp_listen() may return NULL if no memory was available for the listening connection. If so, the memory associated with the pcb passed as an argument to tcp_listen() will not be deallocated.
s t r u c t t c p_p c b*t c p_l i s t e n_w i t h_b a c k l o g(s t r u c t t c p_p c b*p c b,u8_t b a c k l o g)
Same as tcp_listen(), but limits the number of outstanding connections in the listen queue to the valu
e specified by the backlog argument. To use it, your need to set
TCP_LISTEN_BACKLOG=1 in your lwipopts.h.
v o i d t c p_a c c e p t(s t r u c t t c p_p c b*p c b,
e r r_t(*a c c e p t)(v o i d*a r g,s t r u c t t c p_p c b*n e w p c b,
e r r_t e r r))
Commands a pcb to start listening for incoming connections. You must have previously called tcp_listen(). When a new connection arrives on the local port, the specified function will be called with the pcb for the new connection.
v o i d t c p_a c c e p t e d(s t r u c t t c p_p c b*p c b)
Inform lwIP that an incoming connection has been accepted. This would usually be called from the accept callback. This allows lwIP to perform housekeeping tasks, such as allowing further incoming connections to be queued in the listen backlog. The "pcb" parameter is the listening pcb, not the new connection.
e r r_t t c p_c o n n e c t(s t r u c t t c p_p c b*p c b,s t r u c t i p_a d d r*i p a d d r,
u16_t p o r t,e r r_t(*c o n n e c t e d)(v o i d*a r g,
s t r u c t t c p_p c b*t p c b,
e r r_t e r r));
Sets up the pcb to connect to the remote host and sends the initial SYN segment which opens the connection. If the connection has not already been bound to a local port, a local port is assigned to it.
The tcp_connect() function returns immediately; it does not wait for the connection to be properly setup. Instead, it will call the function specified as the fourth argument (the "connected" argument) when the connection is established. If the connection could not be properly established, either because the other host refused the connection or because the other host didn't answer, the "connected" function will be called with an the "err" argument set accordingly.
The tcp_connect() function can return ERR_MEM if no memory is available for enqueueing the SYN segment. If the SYN indeed was enqueued successfully, the tcp_connect() function returns ERR_OK.
Sending TCP data
To send data on a TCP connection:
1. Call tcp_sent() to specify a callback function for acknowledgements.
2. Call tcp_sndbuf() to find the maximum amount of data that can be sent.
3. Call tcp_write() to enqueue the data.
4. Call tcp_output() to force the data to be sent.
u16_t t c p_s n d b u f(s t r u c t t c p_p c b*p c b)
Returns the number of bytes of space available in the output queue.
e r r_t t c p_w r i t e(s t r u c t t c p_p c b*p c b,v o i d*d a t a p t r,u16_t l e n,
u8_t a p i f l a g s)
Enqueues the data pointed to by the argument dataptr. The length of the data is passed as the len parameter.
The apiflags argument can have either of the following bits:
TCP_WRITE_FLAG_COPY indicates that lwIP should allocate new memory and copy the data into it. If not specified, no new memory should be allocated and the data should only be referenced by pointer.
TCP_WRITE_FLAG_MORE indicates that the push flag should not be set in the TCP segment.
The tcp_write() function will fail and return ERR_MEM if the length of the data exceeds the current send buffer size or if the length of the queue of outgoing segment is larger than the upper limit defined in lwipopts.h (TCP_SND_QUEUELEN). If the function returns ERR_MEM, the application should wait until some of the currently enqueued data has been successfully received by the other host and try again.
e r r_t t c p_o u t p u t(s t r u c t t c p_p c b*p c b)
Forces all enqueued data to be sent now.
v o i d t c p_s e n t(s t r u c t t c p_p c b*p c b,
e r r_t(*s e n t)(v o i d*a r g,s t r u c t t c p_p c b*t p c b,
u16_t l e n))
Specifies the callback function that should be called when data has been acknowledged by the remote host. The len argument passed to the callback function gives the number of bytes that were acknowledged by the last acknowledgment.
Receiving TCP data
TCP data reception is callback based; an application-specified callback function is called when new data arrives.
The TCP protocol specifies a window that tells the sending host how much data it can send on the connection. The window size for all connections is TCP_WND which may be overridden in lwipopts.h. When the application has processed the incoming data, it must call the tcp_recved() function to indicate that TCP can increase the receive window.
v o i d t c p_r e c v(s t r u c t t c p_p c b*p c b,
e r r_t(*r e c v)(v o i d*a r g,s t r u c t t c p_p c b*t p c b,
s t r u c t p b u f*p,e r r_t e r r))
Sets the callback function that will be called when new data arrives. If there are no errors and the callback function returns ERR_OK, then it is responsible for freeing the pbuf. Otherwise, it must not free the pbuf so that lwIP core code can store it.
If the remote host closes the connection, the callback function will be called with a NULL pbuf to indicate that fact.
v o i d t c p_r e c v e d(s t r u c t t c p_p c b*p c b,u16_t l e n)
Must be called when the application has processed the data and is prepared to receive more. The purpose is to advertise a larger window when the data has been processed. The len argument indicates the length of the processed data.
Application polling
When a connection is idle (i.e., no data is either transmitted or received), lwIP will repeatedly poll the application by calling a specified callback function. This can be used either as a watchdog timer for killing connections that have stayed idle for too long, or as a method of waiting for memory to become available. For instance, if a call to tcp_write() has failed because memory wasn't available, t
he application may use the polling functionality to call tcp_write() again when the connection has been idle for a while.
v o i d t c p_p o l l(s t r u c t t c p_p c b*p c b,
e r r_t(*p o l l)(v o i d*a r g,s t r u c t t c p_p c b*t p c b),
u8_t i n t e r v a l)
Specifies the polling interval and the callback function that should be called to poll the application. The interval is specified in number of TCP coarse grained timer shots, which typically occurs twice a second. An interval of 10 means that the application would be polled every 5 seconds.
Closing and aborting connections
e r r_t t c p_c l o s e(s t r u c t t c p_p c b*p c b)
Closes the connection. The function may return ERR_MEM if no memory was available for closing the connection. If so, the application should wait and try again either by using the acknowledgment callback or the polling functionality. If the close succeeds, the function returns ERR_OK.
The pcb is deallocated by the TCP code after a call to tcp_close().
Note that data can still be received on a closed connection until the remote host acknowledges the close.
v o i d t c p_a b o r t(s t r u c t t c p_p c b*p c b)
Aborts the connection by sending a RST (reset) segment to the remote host. The pcb is deallocated. This function never fails.
ATTENTION: When calling this from one of the TCP callbacks, make sure you always return ERR_ABRT (and never return ERR_ABRT otherwise or you will risk accessing deallocated memory or memory leaks!
v o i d t c p_e r r(s t r u c t t c p_p c b*p c b,
v o i d(*e r r)(v o i d*a r g,e r r_t e r r))
If a connection is aborted because of an error, the application is alerted of this event by the err callback. Errors that might abort a connection include a shortage of memory. The callback function to be called is set using the tcp_err() function.
The error callback function does not get the pcb passed to it as a parameter since the pcb may already have been deallocated.
Miscellaneous TCP Functions
Nagle Algorithm
For a short overview see /wiki/Nagle%27s_algorithm
tcp_nagle_enable ( struct tcp_pcb * aPcb ); // enable the nagle algorithm
tcp_nagle_disable ( struct tcp_pcb * aPcb ); // disable the nagle algorithm
tcp_nagle_disabled ( struct tcp_pcb * aPcb ); // return true if the algorithm is not enabled
Example (for xNetCann created with NETCONN_TCP):
t c p_n a g l e_e n a b l e(x N e t C o n n->p c b.t c p);
If these macros are not defined in your version of lwIP, you should
upgrade to the newest version (1.4.0 at the moment of writing)
if you can't, use (as an emergency)
xNewConn-&p->flags |= TF_NODELAY to disable
xNewConn-&p->flags &= ~TF_NODELAY to enable
( xNewConn-&p->flags & TF_NODELAY ) != 0 to query for disabled
TCP Keepalive
In your lwipopts.h file you need to add
1. define LWIP_TCP_KEEPALIVE 1
Then on each TCP socket that you need keepalive support, you need to enable it via:
/*T u r n o n T C P K e e p a l i v e f o r t h e g i v e n p c b*/
p c b->s o_o p t i o n s|=S O F_K E E P A L I V E;
/*I f y o u n e e d t o c h a n g e t h e t i m e b e t w e e n k e e p a l i v e m e s s a g e s*/
/
*S e t t h e t i m e b e t w e e n k e e p a l i v e m e s s a g e s i n m i l l i-s e c o n d s*/
p c b->k e e p_i n t v l=75000;/*75s e c o n d s*/
Raw TCP Sample Sequence Diagrams
Because the raw TCP implementation is intended to execute primarily via callbacks, its operation tends to be closely tied to the receipt and processing of individual messages. Hence,it is helpful to have at least a passing familiarity with the low-level TCP protocol. For those without previous lwIP experience, it is sometimes not obvious what calls to make when. The following table shows a sequence diagram of interactions between a remote client and a local lwIP server. The interactions shown are for a typical (successful) connection over a request-response protocol (such as HTTP for example).
lwIP Session Establishment (Remote client / local lwIP server)
Remote client
<TCP
Message>
lwIP Stack Action lwIP Server Action Description
<= tcp_new()Create TCP PCB
<= tcp_bind()Bind port number
<= tcp_listen_with_backlog()Create listening endpoint (new PCB allocated)
<= tcp_accept()Set accept callback
<= tcp_arg()Set callback argument [ptr to server data structure]
connect =>Client connect to server
SYN =>Remote stack sends SYN
(allocate new PCB)lwIP creates "pending" session
<= SYN/ACK lwIP responds with SYN/ACK
<= (connect
returns)
Remote stack notifies client of successful connection ACK =>Remote stack sends ACK to complete 3-way handshake (invoke accept callback) =>lwIP notifies app of new session (with new PCB)
<= tcp_accepted()Server accepts connection, decrements "pending" session count
<= tcp_arg()(Server allocates new session structure), sets new callback argument
<= tcp_recv()Server sets recv callback
<= tcp_err()Server sets error/abort callback
<= tcp_sent()Server sets sent callback
<= (Server returns from accept callback
with OK status)
(mark PCB active)
connection established
(data can now be sent by either side)
send =>TCP data =>Client sends request data
(lwIP invokes server recv
callback) =>
<= tcp_write(response_data, len)Server writes response data to client
(lwIP enqueues TCP segment)
<= tcp_write(response_data2, len2)Server writes some more data
(lwIP enqueues TCP segment)Segment may be combined with preceding segment
<= tcp_recved()Server notifies lwIP to advertise larger window
<= (Server returns from recv callback with
OK status)
<= TCP data (lwIP finds queued segments to
be sent)
lwIP sends data segment(s) to client, including ACK for previously
received client data
Notes: tcp_write() merely enqueues TCP data for later transmission; it does not actually start transmitting. Nevertheless, when tcp_write() is called from within a recv callback as in this example, there is no need to call tcp_output() to start transmission of sent data (indeed, tcp_output() specifically declines to do anything if it is called from within the recv callback). When you have returned from the recv callback, the stack will automatically initiate sending of any data -- and the ACK for the remote client's preceding packet will be combined with the first outgoing data segment. If tcp_write() is called through some other path (perhaps as a result of some event outside of lwIP processing), it may be necessary to call tcp_output to initiate data transmission.
lwIP Session Establishment (Local lwIP client / remote server)
Remote Server
<TCP
Message>
lwIP Stack Action lwIP Client Action Description
<= tcp_new()Create TCP PCB
<= [tcp_bind()]Optionally, bind specific port number or IP address
<= tcp_arg()Allocate client-specific session structure, set as callback argument
<= tcp_err()Set error/abort callback (used to signal connect failure)
<= tcp_recv()Set recv callback (†)
<= tcp_sent()Set sent callback (†)
<= tcp_connect()Connect, providing connected callback
<= SYN<= (lwIP generates SYN)lwIP generates SYN packet to remote server
SYN/ACK
=>
Remote server stack sends SYN/ACK
(lwIP invokes connected
callback) =>
From lwIP point of view, session is now established, final ACK in the 3-part TCP handshake
will be generated on return from the callback
connection established
(data can now be sent by either side)
<= tcp_write(request_data,
len)
Client writes request data to server
(lwIP enqueues TCP
segment)
<= tcp_write(request_data2,
len2)
Client writes some more data
(lwIP enqueues TCP
segment)
Segment may be combined with preceding segment
<= tcp_output()Client signals lwIP to actually generate outgoing packets (*)
<= (Client returns from
connected callback)
<= TCP
data
lwIP generates one or more data packets
send =>TCP data
=>
Server sends response data (lwIP invokes client recv
callback) =>
See preceding table
(†) The recv and sent callbacks can be established after the connection is established (e.g. in the connected callback), if desired.
(*) Note that the call to tcp_output is not actually required if data is written by the client in the connected callback since lwIP will automatically generate an ACK after the callback returns. In other cases, it may be necessary. But see also the note to the previous table.
Notes: In case of a failure to connect, the connecting client is notified of the failure via the error callback set with tcp_err().
Session Termination (Scenario 1 - remote peer shutdown)
Remote client<TCP
Message>lwIP Stack Action lwIP Server
Action
Description
close or
shutdown(SHUT_WR) =>
Client shuts down write end of socket FIN =>Remote stack sends packet with FIN bit set
<= ACK <= (lwIP recognizes FIN, generates immediate
ACK)
lwIP PCB enters CLOSE_WAIT state
(lwIP invokes server recv callback with NULL
pbuf argument) =>
lwIP signals end-of-file to server
[<= tcp_write()]Server sends final data (if any)
...
<= tcp_close()Server frees private data structures, shuts down connection
<= FIN(lwIP generates FIN)lwIP notifies remote stack that server has closed connection (PCB enters LAST_ACK state)
ACK =>Client acknowledges last FIN
lwIP processes last ACK PCB enters CLOSED state (and is then released)
Session Termination (Scenario 2 - local server shutdown)
Remote client<TCP Message>lwIP Stack Action lwIP Server Action Description
<= tcp_close()Server shuts down connection <= FIN<= (lwIP generates FIN packet)PCB enters FIN_WAIT_1 state
ACK =>(lwIP updates PCB)PCB enters FIN_WAIT_2 state
[send] =>[TCP Data] =>Client (optionally) sends last data (*)
...
close =>Client shuts down socket
FIN =>Remote stack sends FIN packet
<= ACK<= (lwIP recognizes FIN, generates ACK)lwIP PCB enters TIME_WAIT
(lwIP invokes server recv callback with NULL pbuf argument) =>lwIP signals end-of-file to server
Server frees private data structures
...
(TIME_WAIT timer expires)lwIP frees PCB
(*) Note that lwIP may invoke server recv callback after server calls tcp_close(). If you don't want to receive these, make sure to zero out the recv callback (i.e. invoke tcp_recv with a NULL pointer).
Categories:LwIP Application Developers Manual Add category
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论