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,都需要大量耐心的测试来确保你的服务器程序确实是按照你的意愿在跑,因为这个选项对服务器处理小量请求的行为影响非常细微,简单的功能测试很难验证它的行为,上线后量大的情况下可能会出问题,让你的服务器马上下线,大并发量的模拟实际场景压测才能保证其正确性:)

————————————————
版权声明:本文为CSDN博主「fhqlongteng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fhqlongteng/article/details/106119058

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值