1. 程式人生 > >lwip-1.4.1文件rawapi中文翻譯

lwip-1.4.1文件rawapi中文翻譯

Raw TCP/IP interface for lwIP
LwIP原始 TCP/IP介面 

如果您想要了解相關內容,可以點選跳轉本文所在的系列的檢索目錄,點選跳轉

Authors: Adam Dunkels, Leon Woestenberg, Christiaan Simons


lwIP provides three Application Program's Interfaces (APIs) for programs
to use for communication with the TCP/IP code:
* low-level "core" / "callback" or "raw" API.
* higher-level "sequential" API.
* BSD-style socket API.
LwIP為程式(上層應用程式)提供了三種應用程式介面,用於和 TCP/IP的程式碼通訊,三種介面如下:
底層的“核心”/“回撥函式”或“原始”API
較高層次的有序 API
BSD樣式的套接 API


The sequential API provides a way for ordinary, sequential, programs
to use the lwIP stack. It is quite similar to the BSD socket API. The
model of execution is based on the blocking open-read-write-close
paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
code and the application program must reside in different execution
contexts (threads).
有序 API提供一種常規、有序的程式設計方法來使用 LwIP堆疊。其非常相似於 BSD套接 API。
其執行模型是基於阻塞的開啟-讀-寫-關閉的正規化。由於 TCP/IP本質上是事件驅動的,
TCP/IP程式碼和應用程式必須駐留在不同的執行緒中。 


The socket API is a compatibility API for existing applications,
currently it is built on top of the sequential API. It is meant to
provide all functions needed to run socket API applications running
on other platforms (e.g. unix / windows etc.). However, due to limitations
in the specification of this API, there might be incompatibilities
that require small modifications of existing programs.
套接 API是一個與現有應用程式相容的 API,當前,它是建立在有序 API的基礎之上。
它為需要在其他平臺(如 Unix和 Windows等)執行的套接 API 的應用程式提供完整的功能。
但由於 API在規格方面的限制,現有程式可能存在與之不相容的地方,進而需要微小的調整。


** Threading
執行緒


lwIP started targeting single-threaded environments. When adding multi-
threading support, instead of making the core thread-safe, another
approach was chosen: there is one main thread running the lwIP core
(also known as the "tcpip_thread"). The raw API may only be used from
this thread! Application threads using the sequential- or socket API
communicate with this main thread through message passing.
LwIP最初以單執行緒環境為目標。當加入多執行緒支援時,鑑於核心執行緒安全的考量,
採取了另一種方法:一個主執行緒執行LwIP核心(也被稱作“tcpip_thread”)。
原始 API可能只在該執行緒中使用。應用程式執行緒採用有序 API或套接 API通過訊息投遞與主執行緒通訊。


      As such, the list of functions that may be called from
      other threads or an ISR is very limited! Only functions
      from these API header files are thread-safe:
      同樣地,被其他執行緒或中斷服務程式呼叫的函式是非常地有限。
      只有如下 API標頭檔案中的函式是執行緒安全的: 
      - api.h
      - netbuf.h
      - netdb.h
      - netifapi.h
      - sockets.h
      - sys.h


      Additionaly, memory (de-)allocation functions may be
      called from multiple threads (not ISR!) with NO_SYS=0
      since they are protected by SYS_LIGHTWEIGHT_PROT and/or
      semaphores.
      此外,當 NO_SYS=0 時,記憶體的分配和釋放函式可能被多個執行緒(不是中斷服務程式)呼叫,
      因此它們(需)通過SYS_LIGHTWEIGHT_PROT巨集定義和(或)訊號量來保護。


      Only since 1.3.0, if SYS_LIGHTWEIGHT_PROT is set to 1
      and LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1,
      pbuf_free() may also be called from another thread or
      an ISR (since only then, mem_free - for PBUF_RAM - may
      be called from an ISR: otherwise, the HEAP is only
      protected by semaphores).
      僅從 1.3.0版本開始,如果 SYS_LIGHTWEIGHT_PROT置 1,pbuf_free()可由其他執行緒或中斷服務程式呼叫
      (僅從那時開始,對 PBUF_MEM的 mem_free函式可能被其他中斷服務程式呼叫:否則,HEAP僅能通過訊號量保護)。 
      


** The remainder of this document discusses the "raw" API. **
該文件的以下內容討論原始 API


The raw TCP/IP interface allows the application program to integrate
better with the TCP/IP code. Program execution is event based by
having callback functions being called from within the TCP/IP
code. The TCP/IP code and the application program both run in the same
thread. The sequential API has a much higher overhead and is not very
well suited for small systems since it forces a multithreaded paradigm
on the application.
原始 TCP/IP介面允許應用程式與 TCP/IP程式碼更好的整合。
應用程式的執行是通過呼叫 TCP/IP 程式碼中的回撥函式來實現事件驅動的。
TCP/IP程式碼和應用程式執行在同一個程序裡。有序 API模式需要較高的開銷,其不適合於小型的系統,
因此,迫使應用程式使用多執行緒正規化。


The raw TCP/IP interface is not only faster in terms of code execution
time but is also less memory intensive. The drawback is that program
development is somewhat harder and application programs written for
the raw TCP/IP interface are more difficult to understand. Still, this
is the preferred way of writing applications that should be small in
code size and memory usage.
原始 API不僅在程式碼執行方面更快,其對儲存器密度要求也較低。缺點是程式開發較為困難,
為原始 API寫的應用程式較難於理解。然而,對於要求具有較小的程式碼尺寸和記憶體使用的場合,
其不失為一種受歡迎的方式。 


Both APIs can be used simultaneously by different application
programs. In fact, the sequential API is implemented as an application
program using the raw TCP/IP interface.
各種 API可以同時被不同的應用程式呼叫(使用)。事實上,有序 API是採用原始 API介面實現的一個應用程式。 


--- Callbacks回撥函式


Program execution is driven by callbacks. Each callback is an ordinary
C function that is called from within the TCP/IP code. Every callback
function is passed the current TCP or UDP connection state as an
argument. Also, in order to be able to keep program specific state,
the callback functions are called with a program specified argument
that is independent of the TCP/IP state.
程式的執行有回撥函式驅動。每個回撥函式都是一個普通的 C函式,這些 C函式由 TCP/IP程式碼呼叫。
每一個回撥函式作為引數傳遞當前的 TCP或 UDP連線狀態。同時,為了能夠保持程式的特定狀態,
回撥函式被指定引數的程式呼叫,回撥函式與 TCP/IP狀態無關。


The function for setting the application connection state is:
用於設定應用程式的連線狀態的函式是: 


- void tcp_arg(struct tcp_pcb *pcb, void *arg)


  Specifies the program specific state that should be passed to all
  other callback functions. The "pcb" argument is the current TCP
  connection control block, and the "arg" argument is the argument
  that will be passed to the callbacks.
  指定程式的特定狀態,該程式的返回控制代碼應傳遞給所有其他的回撥函式。
  “pcb”引數是當前 TCP連線控制塊;“arg”引數是回撥函式返回時的狀態引數。
  (該函式有兩個引數,pcb是使用者分配的 TCP連線控制塊;arg是回撥函式返回時,
  存放回調函式某些引數或狀態的指標;該函式返回的控制代碼應作為引數傳遞給其他回撥函式) 


  
--- TCP connection setup TCP連線建立


The functions used for setting up connections is similar to that of
the sequential API and of the BSD socket API. A new TCP connection
identifier (i.e., a protocol control block - PCB) is created with the
tcp_new() function. This PCB can then be either set to listen for new
incoming connections or be explicitly connected to another host.
用於建立連線的函式類似於有序 API和 BSD套接 API。
一個新的 TCP連線標識(如,協議控制塊 PCB)通過 tcp_new()函式建立。
建立完畢,該 PCB即可用於監聽新到來的連線,也可明確地連線到其他主機。 


- struct tcp_pcb *tcp_new(void)


  Creates a new connection identifier (PCB). If memory is not
  available for creating the new pcb, NULL is returned.
  建立一個新的連線標識。如果記憶體不足,返回 NULL. 


- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
                 u16_t port)


  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 another connection is bound to the same port, the function will
  return ERR_USE, otherwise ERR_OK is returned.
  將 pcb繫結到本地 IP地址和埠號。為了繫結連線至所有本地 IP地址,IP地址可指定為 IP_ADDR_ANY。 
  如果另一個連線已繫結到相同的埠,該函式將返回 ERR_USE,否則返回 ERR_OK。 


- struct tcp_pcb *tcp_listen(struct tcp_pcb *pcb)


  Commands a pcb to start listening for incoming connections. When an
  incoming connection is accepted, the function specified with the
  tcp_accept() function will be called. The pcb will have to be bound
  to a local port with the tcp_bind() function.
  命令一個 PCB 開始監聽即將到來的連線。當新到來的連線被接受,指定 tcp_accept()函式將被呼叫。
  PCB 必須通過tcp_bind()繫結到本地的一個埠。


  The tcp_listen() function returns a new connection identifier, 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.
  tcp_listen()返回一個新的連線標識。同時,作為引數傳遞給該函式的 PCB 將被釋放。
  原因是處於監聽狀態的連線僅需少量的記憶體,因此 tcp_listen()將回收初始連線的記憶體,併為監聽連線分配一個新的較小的記憶體塊。 


  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.
  當用於監聽連線的記憶體不足時(不可獲得時),tcp_listen()將返回 NULL。在這種情況下,
  作為引數傳遞給tcp_listen()的記憶體塊將不會被釋放。
   


- struct tcp_pcb *tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)


  Same as tcp_listen, but limits the number of outstanding connections
  in the listen queue to the value specified by the backlog argument.
  To use it, your need to set TCP_LISTEN_BACKLOG=1 in your lwipopts.h.
  與 tcp_listen相同,但限制了在監聽佇列中未完成(等待)連線的數量,其值由 backlog引數指定。
  使用該函式需在lwipopts.h檔案中將 TCP_LISTEN_BACKLOG置 1。 


- void tcp_accepted(struct tcp_pcb *pcb)


  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.
  通知 LwIP一個新的連線已經被接受。該函式通常被“接受回撥函式”呼叫。
  這允許 LwIP執行內務操作任務,比如允許後續即將到來的連線進入監聽後備佇列。 
  ATTENTION: the PCB passed in must be the listening pcb, not the pcb passed
  into the accept callback!


- void tcp_accept(struct tcp_pcb *pcb,
                  err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
                                   err_t err))


  Specified the callback function that should be called when a new
  connection arrives on a listening connection.
  指定應呼叫的回撥函式,當在一個監聽連線上到來一個新的連線時。 


- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
                    u16_t port, err_t (* connected)(void *arg,
                                                    struct tcp_pcb *tpcb,
                                                    err_t err));


  Sets up the pcb to connect to the remote host and sends the
  initial SYN segment which opens the connection. 
  設定 PCB以連線至遠端主機,併發送用於開啟連線的初始 SYN引數。 


  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 "err"
  callback function of this pcb (registered with tcp_err, see below)
  will be called.
  tcp_connect()函式立即返回;它並不等待連線的正確建立,而是在連線建立時呼叫第四個引數指定的回撥函式。
  如果連線不能正常建立,或因其他主機拒絕建立連線,或其他主機沒有應答,
  該 pcb(以 pcb_err註冊,見下文)的“err” 回撥函式將被呼叫。


  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.
  如果對入隊的 SYN引數沒有可獲得的記憶體,tcp_connect()將返回 ERR_MEM。如果 SYN引數成功入隊,tcp_connect()將返回 ERR_OK。




--- Sending TCP data傳送 TCP資料


TCP data is sent by enqueueing the data with a call to
tcp_write(). When the data is successfully transmitted to the remote
host, the application will be notified with a call to a specified
callback function.
TCP資料的傳送是通過入隊資料並呼叫 tcp_write()來實現的。
當資料成功傳輸至遠端主機時,遠端主機呼叫指定的回撥函式通知應用程式。


- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len,
                  u8_t apiflags)


  Enqueues the data pointed to by the argument dataptr. The length of
  the data is passed as the len parameter. The apiflags can be one or more of:
  - TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated
    for the data to be copied into. If this flag is not given, no new memory
    should be allocated and the data should only be referenced by pointer. This
    also means that the memory behind dataptr must not change until the data is
    ACKed by the remote host
  - TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is given,
    the PSH flag is set in the last segment created by this call to tcp_write.
    If this flag is given, the PSH flag is not set.
    將資料入隊寫至由引數 dataptr指定的記憶體區域。資料的長度作為 len引數傳遞。
    拷貝引數為 0或 1,用於指示是否為將要拷貝來的資料分配新的記憶體。
    如果該引數為 0,將不分配新的記憶體,並且資料僅能通過指標來引用。 


  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. The number of bytes available in the output queue can
  be retrieved with the tcp_sndbuf() function.
  如果資料的最大長度超過了當前傳送資料緩衝區的大小,或輸出片段佇列的長度超過了 lwipopts.h檔案中定義的上限,
  tcp_write()將失敗並返回 EER_MEM,在輸出佇列中可獲得的位元組數可通過 tcp_sndbuf()函式檢索。 


  The proper way to use this function is to call the function with at
  most tcp_sndbuf() bytes of data. 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.
  使用該函式的正確方式是呼叫該函式,並將引數指定為 tcp_sndbuf()獲得的最大位元組數。
  如果函式返回 ERR_MEM,應用程式應等待直到當前入隊資料正確地被其他主機接受並重試。 


- void tcp_sent(struct tcp_pcb *pcb,
                err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
                u16_t len))


  Specifies the callback function that should be called when data has
  successfully been received (i.e., acknowledged) by the remote
  host. The len argument passed to the callback function gives the
  amount bytes that was acknowledged by the last acknowledgment.
  指定當資料被遠端主機成功接收時應呼叫的回撥函式。傳遞給回撥函式的 len 引數給出了在最後一次確認中確認的位元組數。


  
--- Receiving TCP data接收 TCP資料


TCP data reception is callback based - an application specified
callback function is called when new data arrives. When the
application has taken the data, it has to call the tcp_recved()
function to indicate that TCP can advertise increase the receive
window.
TCP資料接收是基於回撥函式的——當新的資料到達時,應用程式指定的回撥函式被呼叫。
當應用程式接收資料完畢,必須呼叫 tcp_recved()函式用於指示 TCP通告可以增加新的接收視窗。


- void tcp_recv(struct tcp_pcb *pcb,
                err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
                               struct pbuf *p, err_t err))


  Sets the callback function that will be called when new data
  arrives. The callback function will be passed a NULL pbuf to
  indicate that the remote host has closed the connection. If
  there are no errors and the callback function is to return
  ERR_OK, then it must free the pbuf. Otherwise, it must not
  free the pbuf so that lwIP core code can store it.
  當新的資料到達時,設定被呼叫的回撥函式。如果遠端主機已關閉了連線,該函式的 pbuf引數將返回一個 NULL空指標。
  如沒有錯誤,並且回撥函式的該引數返回值為 ERR_OK,那麼該函式必須釋放 pbuf。否則,禁止釋放 pbuf,以確保 LwIP核心程式碼可以儲存其值。


- void tcp_recved(struct tcp_pcb *pcb, u16_t len)


  Must be called when the application has received the data. The len
  argument indicates the length of the received data.
  當應用程式已接收資料,必須呼叫此函式。Len引數指示接收資料的長度。 




--- 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,
the application may use the polling functionality to call tcp_write()
again when the connection has been idle for a while.
當連線處於空閒狀態(比如沒有資料收發),LwIP將通過特定的回撥函式重複地詢問應用程式。
在這種情況下,可以用看門狗定時器來切斷長時間處於空閒狀態的連線,也可以用這種方法等待獲取記憶體的分配。
例如,由於記憶體暫時不可獲得,呼叫 tcp_write()將失敗,應用程式可在連線處於空閒狀態時用輪詢功能來再次呼叫 tcp_write()。 


- void tcp_poll(struct tcp_pcb *pcb, 
                err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
                u8_t interval)


  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.
  指定輪詢間隔,並呼叫該回調函式輪詢應用程式。時間間隔由粗略的定時器中斷時間來指定,通常 1秒鐘發生 2次。
  值為10的間隔表示應用程式每隔 5秒查詢一次。 




--- Closing and aborting connections關閉並中止連線


- err_t tcp_close(struct tcp_pcb *pcb)


  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.
  關閉連線。如果關閉連線的記憶體不可獲得,該函式將返回 ERR_MEM。
  在這種情況下,應用程式應通過確認回撥函式或輪詢功能來等待並重試。如果關閉成功,該函式返回 ERR_OK。


  The pcb is deallocated by the TCP code after a call to tcp_close(). 
  在 tcp_close()呼叫後,pcb由 TCP程式碼釋放其記憶體。


- void tcp_abort(struct tcp_pcb *pcb)


  Aborts the connection by sending a RST (reset) segment to the remote
  host. The pcb is deallocated. This function never fails.
  通過向遠端主機發送一個復位語句以中止連線。同時,pcb釋放。該函式不會失敗。 


  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!
  注意:當從 TCP 的任何一個回撥函式中呼叫該函式時,需確保返回值為 ERR_ABRT
  (從不返回 ERR_ABRT,否則將冒險存取已釋放的記憶體,或記憶體洩露)。




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 are when there is a shortage of memory. The callback
function to be called is set using the tcp_err() function.
如果由於發生錯誤連線中止,應用程式應通過 err 回撥函式對該事件保持警覺。
造成中止連線的錯誤可能是記憶體不足。可呼叫的回撥函式是使用 tcp_err()。 


- void tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg,
       err_t err))


  The error callback function does not get the pcb passed to it as a
  parameter since the pcb may already have been deallocated.
  由於 pcb可能已經被釋放,該回調函式不能獲得作為引數傳遞給其自身的 pcb。 




--- Lower layer TCP interface


TCP provides a simple interface to the lower layers of the
system. During system initialization, the function tcp_init() has
to be called before any other TCP function is called. When the system
is running, the two timer functions tcp_fasttmr() and tcp_slowtmr()
must be called with regular intervals. The tcp_fasttmr() should be
called every TCP_FAST_INTERVAL milliseconds (defined in tcp.h) and
tcp_slowtmr() should be called every TCP_SLOW_INTERVAL milliseconds.
TCP為系統的底層提供了一個較為簡單的介面。在系統初始化期間,函式 tcp_init()應先於其他 TCP函式被呼叫。
在系統執行時,兩個定時器函式 tcp_fasttmr()和 tcp_slowtmr()必須以特定的時間間隔呼叫。
tcp_fasttmr()應該每 TCP_FAST_INTERVAL毫秒呼叫一次(定義在 tcp.h檔案中),tcp_slowtmr()應每隔 TCP_SLOW_INTERVAL毫秒呼叫一次。 




--- UDP interface UDP介面


The UDP interface is similar to that of TCP, but due to the lower
level of complexity of UDP, the interface is significantly simpler.
UDP介面與 TCP類似,但由於 UDP底層的複雜性,但其介面卻更為簡單。 


- struct udp_pcb *udp_new(void)


  Creates a new UDP pcb which can be used for UDP communication. The
  pcb is not active until it has either been bound to a local address
  or connected to a remote address.
  建立一個用於 UDP通訊的 pcb。除非 pcb被繫結到一個本地地址或連線到遠端地址,否則該 pcb處於非活動狀態。 


- void udp_remove(struct udp_pcb *pcb)


  Removes and deallocates the pcb.  
  刪除並釋放 pcb。
  
- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr,
                 u16_t port)


  Binds the pcb to a local address. The IP-address argument "ipaddr"
  can be IP_ADDR_ANY to indicate that it should listen to any local IP
  address. The function currently always return ERR_OK.
  將 pcb繫結到一個本地地址。IP 地址引數可以指定為 IP_ADDR_ANY,用以表明其監聽本地所有 IP地址。該函式總是返回 ERR_OK 


- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr,
                    u16_t port)


  Sets the remote end of the pcb. This function does not generate any
  network traffic, but only set the remote address of the pcb.
  設定 pcb的遠端端。該函式不產生任何網路流量,僅僅設定 pcb的遠端終端地址。 


- err_t udp_disconnect(struct udp_pcb *pcb)


  Remove the remote end of the pcb. This function does not generate
  any network traffic, but only removes the remote address of the pcb.
  刪除 pcb的遠端端。該函式不產生任何網路流量,僅僅刪除 pcb的遠端終端地址。 


- err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)


  Sends the pbuf p. The pbuf is not deallocated.
  傳送引數 p指向的內容。Pbuf不被釋放。 


- void udp_recv(struct udp_pcb *pcb,
                void (* recv)(void *arg, struct udp_pcb *upcb,
                                         struct pbuf *p,
                                         ip_addr_t *addr,
                                         u16_t port),
                              void *recv_arg)


  Specifies a callback function that should be called when a UDP
  datagram is received.
  指定當接收到 UDP報文時應呼叫的回撥函式。 
  


--- System initalization系統初始化


A truly complete and generic sequence for initializing the lwip stack
cannot be given because it depends on the build configuration (lwipopts.h)
and additional initializations for your runtime environment (e.g. timers).
取決於編譯配置(lwipopts.h)及執行環境(如定時器)的附加初始化,我們不能給出一個真實、完整、通用的初始化LwIP堆疊的順序。


We can give you some idea on how to proceed when using the raw API.
We assume a configuration using a single Ethernet netif and the
UDP and TCP transport layers, IPv4 and the DHCP client.
我們僅能給出一些使用原始 API的處理方法。假定我們使用單網路 netif、UDP和 TCP、IPv4和 DHCP客戶端的配置。


Call these functions in the order of appearance:
以出現順序呼叫如下函式:


- stats_init()


  Clears the structure where runtime statistics are gathered.
  清除收集執行統計資訊的結構。 


- sys_init()
  
  Not of much use since we set the NO_SYS 1 option in lwipopts.h,
  to be called for easy configuration changes.
  由於我們在 lwipopts.h檔案中將 NO_SYS置 1,所以該函式沒太大的用處。對於簡單配置的改變應呼叫此函式。 


- mem_init()


  Initializes the dynamic memory heap defined by MEM_SIZE.
  初始化由 MEM_SIZE定義的記憶體堆。


- memp_init()


  Initializes the memory pools defined by MEMP_NUM_x.
  初始化由 MEMP_NUM_x定義的記憶體池。


- pbuf_init()


  Initializes the pbuf memory pool defined by PBUF_POOL_SIZE.
  初始化由 PBUF_POOL_SIZE定義的 pbuf記憶體池。
  
- etharp_init()


  Initializes the ARP table and queue.
  Note: you must call etharp_tmr at a ARP_TMR_INTERVAL (5 seconds) regular interval
  after this initialization.
  初始化 ARP表和佇列。註釋:此初始化完畢,必須以 ARP_TMR_INTERVAL(5秒)間隔呼叫 etharp_tmr函式。 


- ip_init()


  Doesn't do much, it should be called to handle future changes.
  應呼叫處理後續的改變,此處沒處理特別的事務。 


- udp_init()


  Clears the UDP PCB list.
  清除 UDP的 PCB列表。


- tcp_init()


  Clears the TCP PCB list and clears some internal TCP timers.
  清除 TCP 的 PCB 列表,並且清除某些內部的 TCP 定時器。
  Note: you must call tcp_fasttmr() and tcp_slowtmr() at the
  predefined regular intervals after this initialization.
  註釋:此初始化完畢,必須以實現定義的時間間隔呼叫tcp_fasttmr()和 tcp_slowtmr()。   
  
- netif_add(struct netif *netif, ip_addr_t *ipaddr,
            ip_addr_t *netmask, ip_addr_t *gw,
            void *state, err_t (* init)(struct netif *netif),
            err_t (* input)(struct pbuf *p, struct netif *netif))


  Adds your network interface to the netif_list. Allocate a struct
  netif and pass a pointer to this structure as the first argument.
  Give pointers to cleared ip_addr structures when using DHCP,
  or fill them with sane numbers otherwise. The state pointer may be NULL.
  在 netif_list中新增網路介面,分配 netif結構並向這個結構的第一個引數傳遞一個指標。
  當使用 DHCP時,給出指向已清空的 ip_addr結構的指標,否則,應正確地賦值。State引數可能是空指標 NULL。 


  The init function pointer must point to a initialization function for
  your ethernet netif interface. The following code illustrates it's use.
  初始化函式指標必須指向使用者的網路 netif介面初始化函式。以下程式碼闡述了它的用法。
  
  err_t netif_if_init(struct netif *netif)
  {
    u8_t i;
    
    for(i = 0; i < ETHARP_HWADDR_LEN; i++) netif->hwaddr[i] = some_eth_addr[i];
    init_my_eth_device();
    return ERR_OK;
  }
  
  For ethernet drivers, the input function pointer must point to the lwip
  function ethernet_input() declared in "netif/etharp.h". Other drivers
  must use ip_input() declared in "lwip/ip.h".
  對於網路驅動,輸入函式指標必須指向在"netif/etharp.h"宣告的 LwIP 函式 ethernet_input()。
  其他驅動必須使用在"lwip/ip.h"宣告的 ip_input()函式。 
  
- netif_set_default(struct netif *netif)


  Registers the default network interface.
  註冊預設的網路介面。


- netif_set_up(struct netif *netif)


  When the netif is fully configured this function must be called.
  當 netif配置完整,必須呼叫該函式。 


- dhcp_start(struct netif *netif)


  Creates a new DHCP client for this interface on the first call.
  Note: you must call dhcp_fine_tmr() and dhcp_coarse_tmr() at
  the predefined regular intervals after starting the client.
  為該介面的第一次呼叫建立一個新的 DHCP 客戶端。
  註釋:在啟動這個客戶端後,必須以實現定義的時間間隔呼叫dhcp_fine_tmr()和 dhcp_coarse_tmr()函式。
  
  You can peek in the netif->dhcp struct for the actual DHCP status.
  使用者可以通過 netif結構中的 netif->dhcp成員來檢視實際的 DHCP狀態。




--- Optimalization hints 優化提示 


The first thing you want to optimize is the lwip_standard_checksum()
routine from src/core/inet.c. You can override this standard
function with the #define LWIP_CHKSUM <your_checksum_routine>.
優化工作的第一件事情就是 src/core/inet.c 中的 lwip_standard_checksum()程式。
使用者可以通過#define LWIP_CHKSUM <your_checksum_routine>巨集定義,使用使用者的函式來取代標準函式。 


There are C examples given in inet.c or you might want to
craft an assembly function for this. RFC1071 is a good
introduction to this subject.
在 inet.c檔案中有 C程式的例子。你可能想要為之編制一個彙編程式。RFC1071對該主題做了詳細的介紹。 


Other significant improvements can be made by supplying
assembly or inline replacements for htons() and htonl()
if you're using a little-endian architecture.
如果你採用小端結構,可通過採用彙編或內聯彙編嵌入來實現 htons()和 htonl()以獲得重要的效能提升。
#define LWIP_PLATFORM_BYTESWAP 1
#define LWIP_PLATFORM_HTONS(x) <your_htons>
#define LWIP_PLATFORM_HTONL(x) <your_htonl>


Check your network interface driver if it reads at
a higher speed than the maximum wire-speed. If the
hardware isn't serviced frequently and fast enough
buffer overflows are likely to occur.
檢測你的網路介面驅動是否讀取的速度高於最大的線速。如果硬體不能足夠快速、頻繁地服務,那麼快取溢位就可能會發生


E.g. when using the cs8900 driver, call cs8900if_service(ethif)
as frequently as possible. When using an RTOS let the cs8900 interrupt
wake a high priority task that services your driver using a binary
semaphore or event flag. Some drivers might allow additional tuning
to match your application and network.
例如,在使用 CS8900驅動時,儘可能頻繁地呼叫 cs8900if_service(ethif)。
當執行實時作業系統時,讓 CS8900中斷喚醒較高優先順序的任務,而該任務採用訊號量或事件標誌來為你的驅動提供服務。
一些驅動可能允許採取其他的調整來匹配你的應用程式和網路。


For a production release it is recommended to set LWIP_STATS to 0.
Note that speed performance isn't influenced much by simply setting
high values to the memory options.
對於正式發行的產品,推薦將 LWIP_STATS置 0。註釋:簡單地將記憶體選項置高對速度效能並沒有太大影響。 


For more optimization hints take a look at the lwIP wiki.
想要獲得更多的優化提示,請檢視 LwIP維基。 


--- Zero-copy MACs 零拷貝 MACs 


To achieve zero-copy on transmit, the data passed to the raw API must
remain unchanged until sent. Because the send- (or write-)functions return
when the packets have been enqueued for sending, data must be kept stable
after that, too.
為了實現傳輸的 0拷貝,傳遞到原始 API 的資料必須保持不被更改直到被髮送。
因為當入隊待發的資料包在入隊後傳送(或寫)函式將返回,入隊後的資料也必須保持不變。 


This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions
must *not* be reused by the application unless their ref-count is 1.
這意味著傳遞給原始 API傳送函式的 pbufs不能被應用程式重複使用,除非他們的 ref-count為 1。


For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too,
but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while
PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change).
對於非拷貝型 pbufs,資料也必須保持不變,但當入隊時,堆疊/驅動將/必須拷貝 PBUF_REF'ed資料,PBUF_ROM-pbufs僅是被入隊(因為 ROM-data不會被改變)。 


Also, data passed to tcp_write without the copy-flag must not be changed!
此外,沒有拷貝標誌 copy-flag傳遞到 tcp_write函式的資料禁止改變。


Therefore, be careful which type of PBUF you use and if you copy TCP data
or not!
因此,要留意你所使用的 PBUF的型別,以及是否拷貝 TCP資料。