lwip協議的配置與裁剪

1、前言 

      最近項目的上使用有線以太網功能,軟件協議使用LWIP協議,操作系統使用Rt thread 3.1.3版本,硬件使用STM32F429+PHY LAN8720方式。這篇記錄總結lwip的詳細配置。

2、配置文件種類

       lwip的配置文件有lwipopts.h和opt.h兩個頭文件,其他中opt.h文件是lwip的默認配置文件,不需要修改此文件,lwipopts.h是用於配置lwip的文件,用戶的對協議的配置請在這個文件中增加與修改,lwipopts.h文件中定義宏會覆蓋到opt.h默認配置宏,讓用戶定義的新宏起作用。由於使用操作系統rt thread, 操作系統中還有一個配置文件rtconfig.h文件,rtconfig.h中有一些關於lwip協議配置的宏。宏會被lwipopts.h所引用。

       

2.1  lwIP爲使用TCP/IP協議通信的應用程序編程提供了兩種接口接口(APIs):

* 低層次的稱之爲"core" / "callback" 或者 "raw" API

* 高層次的稱之爲"sequential" API  

 

       lwIP "sequential" API爲使用TCP/IP協議棧編程提供符合常規的、通用的途徑,它與BSD socket API非常相似。程序的執行過程同樣是基於"open-read-write-close"模型的。從本質上講,TCP/IP協議棧的通信過程是事件驅動的,因此,TCP/IP的代碼和用戶應用程序的代碼必須在不同的線程裏面。

 

 

 

       RAW IP允許應用程序和TCP/IP代碼緊密結合,程序的執行是基於在TCP/IP內核中被調用的回調函數事件驅動的。TCP/IP內核和應用程序可以運行在同一線程。lwIP "sequential" API接口會消耗大量的CPU資源,它並不適用於小型嵌入式系統,因爲它必須運行在多線程環境中。

 

      RAW API不僅執行速度快,而且消耗的內存資源更少。它的缺點是應用程序編寫相對較難並不易理解。儘管如此,這種方式仍是資源較少的嵌入式系統的首選方法。

 

      不同的應用程序中我們可以同時使用這兩種APIs,實際上"sequential" API就是由RAW API封裝後得到的。

2.2 通信接口

      網絡的應用層編程一般都是基於socket接口編程 ,在創建socket時,會指定協議簇及連接類型,lwip協議中連接類型支持3種,TCP類型連接,UDP類型連接, RAW類型的連接。

       socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))   創建一個tcp連接,協議內部使用佔用一個TCP類型的控制塊數據結構

      socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)   創建一個udp連接,協議內部使用佔用一個UDP類型的控制塊數據結構

      socketsocket(AF_INET , SOCK_RAW , IPPROTO_TCP)   創建一個raw(原始)連接,協議內部使用佔用一個RAW類型的控制塊數據結構, 此連接接收到的數據中包含tcp,ip的數據頭部分

 3、 配置頭文件詳細說明

3.1 rtconfig配置文件

        rtconfig文件用於配置整個rt thread操作系統,包括使用的lwip協議,下面只節取其中關於lwip協議部分的配置。

#define RT_USING_LWIP                        /*控制操作系統使用lwip協議  */
/* RT_USING_LWIP141 is not set */
#define RT_USING_LWIP202                     /*選用2.0.2版本的lwip協議  */
/* RT_USING_LWIP210 is not set */
/* RT_LWIP_IGMP is not set */                /* IGMP協議關閉            */
#define RT_LWIP_ICMP                         /* 使能ICMP協議功能        */
/* RT_LWIP_SNMP is not set */
#define RT_LWIP_DNS                          /* 使能DNS 動態域名解析功能 */
#define RT_LWIP_DHCP                         /* 使能DHCP動態主機配置協議功能*/
#define IP_SOF_BROADCAST 1                   /* 使能廣播包過濾功能        */
#define IP_SOF_BROADCAST_RECV 1              /* 使能接收廣播過濾功能      */

/* Static IPv4 Address */

#define RT_LWIP_IPADDR "192.168.10.30"       /*協議配置爲靜態IP時的默認IP地址,網關地址,子網掩碼*/
#define RT_LWIP_GWADDR "192.168.10.1"
#define RT_LWIP_MSKADDR "255.255.255.0"
/* end of Static IPv4 Address */
#define RT_LWIP_UDP                          /*使能udp協議 */
#define RT_LWIP_TCP                          /*使能tcp協議 */
#define RT_LWIP_RAW                          /*使能raw接口編程,此接口是用於支持無操作系統,上層的TCP,UDP socket接口最後會調用RAW接口函數*/
/* RT_LWIP_PPP is not set */
#define RT_MEMP_NUM_NETCONN 8                /*內存池中netcon結構的數量8 這個參數控制着應用層能建立的socet的數量,也就是能同時支持多少個socket連接,此值應該大於MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB)*/
#define RT_LWIP_PBUF_NUM 16                  /*pbuf的數量, pbuf用於以太網數據包的存儲並在協議棧中傳遞數據使用*/
#define RT_LWIP_RAW_PCB_NUM 4                /*協議中支持的RAW控制塊的數量,一個raw(原始)連接佔用一個控制塊,原始連接可以額外處理IP頭,TCP頭,UDP頭等數據*/
#define RT_LWIP_UDP_PCB_NUM 4                /*協議中支持的udp控制塊的數量,一個udp連接佔用一個udp的控制塊*/
#define RT_LWIP_TCP_PCB_NUM 4                /*協議中支持的tcp控制塊的數量,一個tcp連接佔用一個tcp控制塊*/
#define RT_LWIP_TCP_SEG_NUM 40               /* TCP段的數量,應該比TCP發送段數量大TCP_SND_QUEUELEN,此數量用於分配存儲TCP數據段的內存池的數量,即程序能緩衝多少個TCP數據段*/
#define RT_LWIP_TCP_SND_BUF 8196             /*  TCP發送緩存的大小,發送緩存要至少能容納2個TCP段的大小,一個TCP段的大小1460*/
#define RT_LWIP_TCP_WND 8196                 /*  TCP接收窗口的大小,單位字節,TCP根據自己的處理能力調節接收窗口的大小,告知發送方我現在能接收多少數據,實現了類似流量控制的功能*/
#define RT_LWIP_TCPTHREAD_PRIORITY 10        /*  TCP核心處理線程的優先級,建議比底層的MAC數據的接收與發送線程優先級高,實現快速處理掉接收數據*/
#define RT_LWIP_TCPTHREAD_MBOX_SIZE 10        /* TCP核心線程的使用的消息郵箱的大小,消息郵箱大可以緩存更多的處理數據*/
#define RT_LWIP_TCPTHREAD_STACKSIZE 1024      /* TCP核心線程的堆棧大小    */
/* LWIP_NO_RX_THREAD is not set */
/* LWIP_NO_TX_THREAD is not set */
#define RT_LWIP_ETHTHREAD_PRIORITY 13         /*  MAC層數據發送線程和接收線程的優先級  */
#define RT_LWIP_ETHTHREAD_STACKSIZE 1024      /*  MAC層數據發送線程和接收線程的堆棧    */
#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8         /*  MAC層數據發送線程和接收線程的使用的郵箱大小,郵箱變大可以緩存更多的以太網mac層數據  */
/* RT_LWIP_REASSEMBLY_FRAG is not set */
#define LWIP_NETIF_STATUS_CALLBACK 1          /* 使能網絡接口層的狀態回調函數功能      */
#define LWIP_NETIF_LINK_CALLBACK 1            /* 使能網絡接口層的link回調函數功能      */
#define SO_REUSE 1                            /* 使能socket的SO_REUSEADDR功能,具體請見3.2節的功能介紹*/
#define LWIP_SO_RCVTIMEO 1                    /* 使能接收超時功能,即調用接收函數recv, recvfrom可以設置超時間時間,超時到了沒有數據返回錯誤*/
#define LWIP_SO_SNDTIMEO 1                    /* 使能發送超時功能,即調用發送函數send, sendto可以設置超時間時間,超時到了沒有數據返回錯誤*/
#define LWIP_SO_RCVBUF 1                      /* 使能設置socket接收緩衝區在大小的功能選項*/
/* RT_LWIP_NETIF_LOOPBACK is not set */
#define LWIP_NETIF_LOOPBACK 0                 /*  關閉環回網絡接口                     */
/* RT_LWIP_STATS is not set */
/* RT_LWIP_USING_HW_CHECKSUM is not set */    /*  禁止硬件MAC層計算校驗和功能,採用軟件計算                */
#define RT_LWIP_USING_PING                     /* 使能網卡接口ping命令的功能            */                   
/* RT_LWIP_DEBUG is not set */                /*  禁止lwip協議內部的調試打印信息         */
/* end of light weight TCP/IP stack */

     

3.2 SO_REUSEADDR功能

        一般來說,一個端口釋放後會等待兩分鐘2MSL的時間之後才能再被使用,SO_REUSEADDR是讓端口釋放後立即就可以被再次使用。

SO_REUSEADDR用於對TCP套接字處於TIME_WAIT狀態下的socket,纔可以重複綁定使用
server程序總是應該在調用bind()之前設置SO_REUSEADDR套接字選項
TCP,先調用close()的一方會進入TIME_WAIT狀態

SO_REUSEADDR提供如下四個功能:

  • 允許啓動一個監聽服務器並捆綁其衆所周知端口,即使以前建立的將此端口用做他們的本地端口的連接仍存在。這通常是重啓監聽服務器時出現,若不設置此選項,則bind時將出錯
  • 允許在同一端口上啓動同一服務器的多個實例,只要每個實例捆綁一個不同的本地IP地址即可。對於TCP,我們根本不可能啓動捆綁相同IP地址和相同端口號的多個服務器。
  • 允許單個進程捆綁同一端口到多個套接口上,只要每個捆綁指定不同的本地IP地址即可。這一般不用於TCP服務器。
  • SO_REUSEADDR允許完全重複的捆綁:
    當一個IP地址和端口綁定到某個套接口上時,還允許此IP地址和端口捆綁到另一個套接口上。一般來說,這個特性僅在支持多播的系統上纔有,而且只對UDP套接口而言(TCP不支持多播)

 

3.3 lwipopts.h配置文件

         lwipopts.h頭文件用於對lwip協議的配置的用戶自定義部分。其中定義的配置宏比rtconfig.h中還要多一些,如果修改一些在rtconfig.h中沒有配置,可以在此文件中修改。此文件中配置lwip協議的主要配置文件。

ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__

#include <rtconfig.h>

#define ERRNO                       1

#define LWIP_IPV4                   1

#ifdef RT_USING_LWIP_IPV6
#define LWIP_IPV6                   1
#else
#define LWIP_IPV6                   0
#endif /* RT_USING_LWIP_IPV6 */

#define NO_SYS                      0
#define LWIP_SOCKET                 1
#define LWIP_NETCONN                1

#ifdef RT_LWIP_IGMP
#define LWIP_IGMP                   1
#else
#define LWIP_IGMP                   0
#endif

#ifdef RT_LWIP_ICMP
#define LWIP_ICMP                   1
#else
#define LWIP_ICMP                   0
#endif

#ifdef RT_LWIP_SNMP
#define LWIP_SNMP                   1
#else
#define LWIP_SNMP                   0
#endif

#ifdef RT_LWIP_DNS
#define LWIP_DNS                    1
#else
#define LWIP_DNS                    0
#endif

#define LWIP_HAVE_LOOPIF            0          /*關閉環回接口,此宏用於設置本地環回接口的名稱爲localhost接口,打開環回功能時還要設置LWIP_NETIF_LOOPBACK 爲1*/

#define LWIP_PLATFORM_BYTESWAP      0          /*LWIP硬件平臺的字節順序交換功能,未被lwip協議代碼使用這個宏*/

#ifndef BYTE_ORDER
#define BYTE_ORDER                  LITTLE_ENDIAN   /*定義處理器的大端與小端功能,用於變換網絡字節順序與主機順序時使用*/
#endif

/* #define RT_LWIP_DEBUG */

#ifdef RT_LWIP_DEBUG
#define LWIP_DEBUG
#endif

/* ---------- Debug options ---------- */
#ifdef LWIP_DEBUG
#ifdef RT_LWIP_SYS_DEBUG
#define SYS_DEBUG                   LWIP_DBG_ON
#else
#define SYS_DEBUG                   LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_ETHARP_DEBUG
#define ETHARP_DEBUG                LWIP_DBG_ON
#else
#define ETHARP_DEBUG                LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_PPP_DEBUG
#define PPP_DEBUG                   LWIP_DBG_ON
#else
#define PPP_DEBUG                   LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_MEM_DEBUG
#define MEM_DEBUG                   LWIP_DBG_ON
#else
#define MEM_DEBUG                   LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_MEMP_DEBUG
#define MEMP_DEBUG                  LWIP_DBG_ON
#else
#define MEMP_DEBUG                  LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_PBUF_DEBUG
#define PBUF_DEBUG                  LWIP_DBG_ON
#else
#define PBUF_DEBUG                  LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_API_LIB_DEBUG
#define API_LIB_DEBUG               LWIP_DBG_ON
#else
#define API_LIB_DEBUG               LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_API_MSG_DEBUG
#define API_MSG_DEBUG               LWIP_DBG_ON
#else
#define API_MSG_DEBUG               LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCPIP_DEBUG
#define TCPIP_DEBUG                 LWIP_DBG_ON
#else
#define TCPIP_DEBUG                 LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_NETIF_DEBUG
#define NETIF_DEBUG                 LWIP_DBG_ON
#else
#define NETIF_DEBUG                 LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_SOCKETS_DEBUG
#define SOCKETS_DEBUG               LWIP_DBG_ON
#else
#define SOCKETS_DEBUG               LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_DNS_DEBUG
#define DNS_DEBUG                   LWIP_DBG_ON
#else
#define DNS_DEBUG                   LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_AUTOIP_DEBUG
#define AUTOIP_DEBUG                LWIP_DBG_ON
#else
#define AUTOIP_DEBUG                LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_DHCP_DEBUG
#define DHCP_DEBUG                  LWIP_DBG_ON
#else
#define DHCP_DEBUG                  LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_IP_DEBUG
#define IP_DEBUG                    LWIP_DBG_ON
#else
#define IP_DEBUG                    LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_IP_REASS_DEBUG
#define IP_REASS_DEBUG              LWIP_DBG_ON
#else
#define IP_REASS_DEBUG              LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_ICMP_DEBUG
#define ICMP_DEBUG                  LWIP_DBG_ON
#else
#define ICMP_DEBUG                  LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_IGMP_DEBUG
#define IGMP_DEBUG                  LWIP_DBG_ON
#else
#define IGMP_DEBUG                  LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_UDP_DEBUG
#define UDP_DEBUG                   LWIP_DBG_ON
#else
#define UDP_DEBUG                   LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCP_DEBUG
#define TCP_DEBUG                   LWIP_DBG_ON
#else
#define TCP_DEBUG                   LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCP_INPUT_DEBUG
#define TCP_INPUT_DEBUG             LWIP_DBG_ON
#else
#define TCP_INPUT_DEBUG             LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCP_OUTPUT_DEBUG
#define TCP_OUTPUT_DEBUG            LWIP_DBG_ON
#else
#define TCP_OUTPUT_DEBUG            LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCP_RTO_DEBUG
#define TCP_RTO_DEBUG               LWIP_DBG_ON
#else
#define TCP_RTO_DEBUG               LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCP_CWND_DEBUG
#define TCP_CWND_DEBUG              LWIP_DBG_ON
#else
#define TCP_CWND_DEBUG              LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCP_WND_DEBUG
#define TCP_WND_DEBUG               LWIP_DBG_ON
#else
#define TCP_WND_DEBUG               LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCP_FR_DEBUG
#define TCP_FR_DEBUG                LWIP_DBG_ON
#else
#define TCP_FR_DEBUG                LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCP_QLEN_DEBUG
#define TCP_QLEN_DEBUG              LWIP_DBG_ON
#else
#define TCP_QLEN_DEBUG              LWIP_DBG_OFF
#endif

#ifdef RT_LWIP_TCP_RST_DEBUG
#define TCP_RST_DEBUG               LWIP_DBG_ON
#else
#define TCP_RST_DEBUG               LWIP_DBG_OFF
#endif

#endif /* LWIP_DEBUG */

#define LWIP_DBG_TYPES_ON           (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT)

/* ---------- Memory options ---------- */
#define MEM_ALIGNMENT               4    /*動態內存堆中按4字節對齊             */
#define MEMP_OVERFLOW_CHECK         1 // /*使能內存池的溢出檢測功能            */
#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1 ////
//#define MEM_LIBC_MALLOC             1  
//#define MEM_USE_POOLS               1
//#define MEMP_USE_CUSTOM_POOLS       1
//#define MEM_SIZE                    (1024*64)

#define MEMP_MEM_MALLOC             0    /* lwip的內存堆未使用協議自帶的,調用系統的動態內存堆*/

/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
   sends a lot of data out of ROM (or other static memory), this
   should be set high. */
#define MEMP_NUM_PBUF               32 //16

/* the number of struct netconns */
#ifdef RT_MEMP_NUM_NETCONN
#define MEMP_NUM_NETCONN            RT_MEMP_NUM_NETCONN
#endif

/* the number of UDP protocol control blocks. One per active RAW "connection". */
#ifdef RT_LWIP_RAW_PCB_NUM
#define MEMP_NUM_RAW_PCB            RT_LWIP_RAW_PCB_NUM
#endif

/* the number of UDP protocol control blocks. One per active UDP "connection". */
#ifdef RT_LWIP_UDP_PCB_NUM
#define MEMP_NUM_UDP_PCB            RT_LWIP_UDP_PCB_NUM
#endif

/* the number of simulatenously active TCP connections. */
#ifdef RT_LWIP_TCP_PCB_NUM
#define MEMP_NUM_TCP_PCB            RT_LWIP_TCP_PCB_NUM
#endif

/* the number of simultaneously queued TCP */
#ifdef RT_LWIP_TCP_SEG_NUM
#define MEMP_NUM_TCP_SEG            RT_LWIP_TCP_SEG_NUM
#else
#define MEMP_NUM_TCP_SEG            TCP_SND_QUEUELEN
#endif

/*
 * You can re-define following setting in rtcofnig.h to overwrite the default
 * setting in the lwip opts.h
 */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
// #define MEMP_NUM_NETBUF             2
/* MEMP_NUM_NETCONN: the number of struct netconns. */
// #define MEMP_NUM_NETCONN            4

/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used
   for sequential API communication and incoming packets. Used in
   src/api/tcpip.c. */
// #define MEMP_NUM_TCPIP_MSG_API      16
// #define MEMP_NUM_TCPIP_MSG_INPKT    16

/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#ifdef RT_LWIP_PBUF_NUM
#define PBUF_POOL_SIZE               RT_LWIP_PBUF_NUM
#endif

/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#ifdef RT_LWIP_PBUF_POOL_BUFSIZE
#define PBUF_POOL_BUFSIZE            RT_LWIP_PBUF_POOL_BUFSIZE
#endif

/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
   link level header. */
#define PBUF_LINK_HLEN              16

#ifdef RT_LWIP_ETH_PAD_SIZE
#define ETH_PAD_SIZE                RT_LWIP_ETH_PAD_SIZE
#endif

/** SYS_LIGHTWEIGHT_PROT
 * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
 * for certain critical regions during buffer allocation, deallocation and memory
 * allocation and deallocation.
 */
#define SYS_LIGHTWEIGHT_PROT        (NO_SYS==0)   /*使能關鍵的內存分配保護   */

#ifdef LWIP_USING_NAT
#define IP_NAT                      1
#else
#define IP_NAT                      0
#endif

/* ---------- TCP options ---------- */
#ifdef RT_LWIP_TCP
#define LWIP_TCP                    1
#else
#define LWIP_TCP                    0
#endif

#define TCP_TTL                     255

/* Controls if TCP should queue segments that arrive out of
   order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ             1

/* TCP Maximum segment size. */
#define TCP_MSS                     1460      /*  一個tcp段的大小      */

/* TCP sender buffer space (bytes). */
#ifdef RT_LWIP_TCP_SND_BUF
#define TCP_SND_BUF                 RT_LWIP_TCP_SND_BUF
#else
#define TCP_SND_BUF                 (TCP_MSS * 2)
#endif

/* TCP sender buffer space (pbufs). This must be at least = 2 *
   TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN            (4 * TCP_SND_BUF/TCP_MSS)

/* TCP writable space (bytes). This must be less than or equal
   to TCP_SND_BUF. It is the amount of space which must be
   available in the tcp snd_buf for select to return writable */
#define TCP_SNDLOWAT                (TCP_SND_BUF/2)
#define TCP_SNDQUEUELOWAT           TCP_SND_QUEUELEN/2

/* TCP receive window. */
#ifdef RT_LWIP_TCP_WND
#define TCP_WND                     RT_LWIP_TCP_WND
#else
#define TCP_WND                     (TCP_MSS * 2)
#endif

/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX                  12

/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX               4

/* tcpip thread options */
#ifdef RT_LWIP_TCPTHREAD_PRIORITY
#define TCPIP_MBOX_SIZE             RT_LWIP_TCPTHREAD_MBOX_SIZE
#define TCPIP_THREAD_PRIO           RT_LWIP_TCPTHREAD_PRIORITY
#define TCPIP_THREAD_STACKSIZE      RT_LWIP_TCPTHREAD_STACKSIZE
#else
#define TCPIP_MBOX_SIZE             8
#define TCPIP_THREAD_PRIO           128
#define TCPIP_THREAD_STACKSIZE      4096
#endif
#define TCPIP_THREAD_NAME           "tcpip"     /*tcp核心線程的名稱    */
#define DEFAULT_TCP_RECVMBOX_SIZE   10          /*tcp連接接收郵箱的大小*/

/* ---------- ARP options ---------- */
#define LWIP_ARP                    1           /*使能ARP功能       */
#define ARP_TABLE_SIZE              10          /*ARP地址表的大小   */
#define ARP_QUEUEING                1           /* ARP隊列*/

/* ---------- Checksum options ---------- */
#ifdef RT_LWIP_USING_HW_CHECKSUM
#define CHECKSUM_GEN_IP                 0
#define CHECKSUM_GEN_UDP                0
#define CHECKSUM_GEN_TCP                0
#define CHECKSUM_GEN_ICMP               0
#define CHECKSUM_CHECK_IP               0
#define CHECKSUM_CHECK_UDP              0
#define CHECKSUM_CHECK_TCP              0
#define CHECKSUM_CHECK_ICMP             0
#endif

/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
   IP packets across network interfaces. If you are going to run lwIP
   on a device with only one network interface, define this to 0. */
#define IP_FORWARD                  0

/* IP reassembly and segmentation.These are orthogonal even
 * if they both deal with IP fragments */
#ifdef RT_LWIP_REASSEMBLY_FRAG
#define IP_REASSEMBLY               1
#define IP_FRAG                     1
#define IP_REASS_MAX_PBUFS          10
#define MEMP_NUM_REASSDATA          10
#else
#define IP_REASSEMBLY               0
#define IP_FRAG                     0
#endif

/* ---------- ICMP options ---------- */
#define ICMP_TTL                    255

/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
   interfaces. */
#ifdef RT_LWIP_DHCP
#define LWIP_DHCP                   1
#else
#define LWIP_DHCP                   0
#endif

/* 1 if you want to do an ARP check on the offered address
   (recommended). */
#define DHCP_DOES_ARP_CHECK         (LWIP_DHCP)

/* ---------- AUTOIP options ------- */
#define LWIP_AUTOIP                 0
#define LWIP_DHCP_AUTOIP_COOP       (LWIP_DHCP && LWIP_AUTOIP)

/* ---------- UDP options ---------- */
#ifdef RT_LWIP_UDP
#define LWIP_UDP                    1
#else
#define LWIP_UDP                    0
#endif

#define LWIP_UDPLITE                0
#define UDP_TTL                     255
#define DEFAULT_UDP_RECVMBOX_SIZE   1    /* UDP數據的接收的郵箱的大小 */

/* ---------- RAW options ---------- */
#ifdef RT_LWIP_RAW
#define LWIP_RAW                    1
#else
#define LWIP_RAW                    0
#endif

#define DEFAULT_RAW_RECVMBOX_SIZE   1       /* RAW接收郵箱的大小         */
#define DEFAULT_ACCEPTMBOX_SIZE     10      /*accept函數的接收郵箱大小    */

/* ---------- Statistics options ---------- */
#ifdef RT_LWIP_STATS
#define LWIP_STATS                  1
#define LWIP_STATS_DISPLAY          1
#else
#define LWIP_STATS                  0
#endif

#if LWIP_STATS
#define LINK_STATS                  1
#define IP_STATS                    1
#define ICMP_STATS                  1
#define IGMP_STATS                  1
#define IPFRAG_STATS                1
#define UDP_STATS                   1
#define TCP_STATS                   1
#define MEM_STATS                   1
#define MEMP_STATS                  1
#define PBUF_STATS                  1
#define SYS_STATS                   1
#define MIB2_STATS                  1
#endif /* LWIP_STATS */

/* ---------- PPP options ---------- */
#ifdef RT_LWIP_PPP                         /* 使能PPP協議*/
#define PPP_SUPPORT                 1      /* Set > 0 for PPP */
#else
#define PPP_SUPPORT                 0      /* Set > 0 for PPP */
#endif

#if PPP_SUPPORT
#define NUM_PPP                     1      /* Max PPP sessions. */

/* Select modules to enable.  Ideally these would be set in the makefile but
 * we're limited by the command line length so you need to modify the settings
 * in this file.
 */
#ifdef RT_LWIP_PPPOE                      /*使能支持PPOE功能*/
#define PPPOE_SUPPORT               1
#else
#define PPPOE_SUPPORT               0
#endif

#ifdef RT_LWIP_PPPOS
#define PPPOS_SUPPORT               1
#else
#define PPPOS_SUPPORT               0
#endif
/*以下爲ppp協議相關的配置*/
#define PAP_SUPPORT                 1      /* Set > 0 for PAP. */
#define CHAP_SUPPORT                1      /* Set > 0 for CHAP. */
#define MSCHAP_SUPPORT              0      /* Set > 0 for MSCHAP (NOT FUNCTIONAL!) */
#define CBCP_SUPPORT                0      /* Set > 0 for CBCP (NOT FUNCTIONAL!) */
#define CCP_SUPPORT                 0      /* Set > 0 for CCP (NOT FUNCTIONAL!) */
#define VJ_SUPPORT                  1      /* Set > 0 for VJ header compression. */
#define MD5_SUPPORT                 1      /* Set > 0 for MD5 (see also CHAP) */

#endif /* PPP_SUPPORT */

/**
 * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names.
 * Disable this option if you use a POSIX operating system that uses the same
 * names (read, write & close). (only used if you use sockets.c)
 */
#ifndef LWIP_POSIX_SOCKETS_IO_NAMES
#define LWIP_POSIX_SOCKETS_IO_NAMES     0
#endif

/**
 * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT
 * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set
 * in seconds. (does not require sockets.c, and will affect tcp.c)
 */
#ifndef LWIP_TCP_KEEPALIVE               /*使能tcp鏈接的keepalive功能 此功能用於協議棧自動回收長時間沒有數據通信的TCP連接,建議在tcp應用編程中開啓此功能*/
#define LWIP_TCP_KEEPALIVE              1
#endif

/**
 * LWIP_NETIF_API==1: Support netif api (in netifapi.c)
 */
#ifndef LWIP_NETIF_API
#define LWIP_NETIF_API                  1
#endif

#ifdef LWIP_IGMP
#include <stdlib.h>
#define LWIP_RAND                  rand
#endif
/*
   ------------------------------------
   ---------- Socket options ----------
   ------------------------------------
*/
/*
 * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
 */
#ifndef LWIP_SOCKET
#define LWIP_SOCKET                     1
#endif

/*
 * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names.
 * (only used if you use sockets.c)
 */
#ifdef SAL_USING_POSIX
#define LWIP_COMPAT_SOCKETS             0
#else
#ifndef LWIP_COMPAT_SOCKETS
#define LWIP_COMPAT_SOCKETS             1
#endif
#endif

/**
 * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and
 * SO_SNDTIMEO processing.
 */
#ifndef LWIP_SO_SNDTIMEO
#define LWIP_SO_SNDTIMEO                1
#endif

/**
 * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and
 * SO_RCVTIMEO processing.
 */
#ifndef LWIP_SO_RCVTIMEO
#define LWIP_SO_RCVTIMEO                1
#endif

/**
 * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing.
 */
#ifndef LWIP_SO_RCVBUF
#define LWIP_SO_RCVBUF                  1
#endif

/**
 * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize.
 */
#ifndef RECV_BUFSIZE_DEFAULT
#define RECV_BUFSIZE_DEFAULT            8192
#endif

/**
 * SO_REUSE==1: Enable SO_REUSEADDR option.
 */
#ifndef SO_REUSE                        /*請見3.2節的功能介紹說明  */
#define SO_REUSE                        0
#endif

/*
   ------------------------------------
   ------- Applications options -------
   ------------------------------------
*/

/**
 * Max. length of TFTP filename
 */
#ifdef RT_LWIP_TFTP_MAX_FILENAME_LEN
#define TFTP_MAX_FILENAME_LEN           RT_LWIP_TFTP_MAX_FILENAME_LEN
#elif defined(RT_DFS_ELM_MAX_LFN)
#define TFTP_MAX_FILENAME_LEN           RT_DFS_ELM_MAX_LFN
#else
#define TFTP_MAX_FILENAME_LEN           64
#endif

/* Use the hostname*/
#define LWIP_NETIF_HOSTNAME             1


#endif /* __LWIPOPTS_H__ */

     opt.h頭文件中定義了lwip協議的全部配置宏,都設置了默認的配置,如果在lwipopts.h,rtconfig.h中未定義的宏,將採用opt.h中的默認配置,如果想了解更全面的lwip配置請參考opt.h中的配置宏定義。

     lwip配置中還有一個宏  LWIP_SO_LINGER,這個宏lwipopts.h中未使用定義,那麼lwip協議棧採用的是opt.h中默認配置,此配置是關閉的。這個功能有特殊的應用,具體如下文介紹。

      

3.4 LWIP_SO_LINGER作用


    LWIP_SO_LINGER宏用於設置函數close()關閉TCP連接時的行爲。缺省close()的行爲是,如果有數據殘留在socket發送緩衝區中則系統將繼續發送這些數據給對方,等待被確認,然後返回。

利用此選項,可以將此缺省行爲設置爲以下兩種
  a.立即關閉該連接,通過發送RST分組(而不是用正常的FIN|ACK|FIN|ACK四個分組)來關閉該連接。至於發送緩衝區中如果有未發送完的數據,則丟棄。主動關閉一方的TCP狀態則跳過TIMEWAIT,直接進入CLOSED。網上很多人想利用這一點來解決服務器上出現大量的TIMEWAIT狀態的socket的問題,但是,這並不是一個好主意,這種關閉方式的用途並不在這兒,實際用途在於服務器在應用層的需求。
  b.將連接的關閉設置一個超時。如果socket發送緩衝區中仍殘留數據,進程進入睡眠,內核進入定時狀態去儘量去發送這些數據。
    在超時之前,如果所有數據都發送完且被對方確認,內核用正常的FIN|ACK|FIN|ACK四個分組來關閉該連接,close()成功返回。
    如果超時之時,數據仍然未能成功發送及被確認,用上述a方式來關閉此連接。close()返回EWOULDBLOCK。


SO_LINGER選項使用如下結構:

struct linger {

     int l_onoff;

     int l_linger;

};

 

l_onoff爲0,則該選項關閉,l_linger的值被忽略,close()用上述缺省方式關閉連接。

l_onoff非0,l_linger爲0,close()用上述a方式關閉連接。

l_onoff非0,l_linger非0,close()用上述b方式關閉連接。

值得一說的是,不管你用什麼方式使用SO_LINGER,都需要大量耐心的測試來確保你的服務器程序確實是按照你的意願在跑,因爲這個選項對服務器處理小量請求的行爲影響非常細微,簡單的功能測試很難驗證它的行爲,上線後量大的情況下可能會出問題,讓你的服務器馬上下線,大併發量的模擬實際場景壓測才能保證其正確性:)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章