LWIP互联网资料汇总

本文主要搜集了下互联网上关于LWIP的资料和教程

欢迎补充


第一部分:移植

LWIP在UCOS上移植

LWIP 在STM32上移植   http://www.docin.com/p-459242028.html

LWIP移植简介  http://www.doc88.com/p-647607123736.html


第二部分:课件与应用

LWIP概述

LWIP PPT课件

LWIP WIKI

LWIP中文手册

LWIP官方文档

LWIP源代码在线查看  http://www.es.sdu.edu.cn/project/doc/lwip/ref/files.html

LWIP所有版本源代码在线查看 CVS

CSDN上相关博客  

http://blog.csdn.net/zyboy2000/article/category/1140313

http://blog.csdn.net/beisika10368/article/category/742910


WIKI和Email  List

https://savannah.nongnu.org/projects/lwip/
http://en.wikipedia.org/wiki/LwIP
http://lists.nongnu.org/mailman/listinfo/lwip-users


lwip提供三种API:1)RAW API 2)lwip API 3)BSD API。

LWIP应用指南   RAW-API使用

RAW-API函数在线查看

Netconn API函数在线查看   

SOCKET API在线查看



第三部分:内核与实现

LWIP分析  http://wenku.baidu.com/view/a448821b6bd97f192279e947.html###

LWIP socket实现

LWIP协议栈分析

LWIP设计与实现

LWIP源码详解

LWIP协议栈源码详解-老衲五木


第四部分:简单实例(三种API:1)RAW API 2)lwip API 3)BSD API。)

编程时可参考LWIP WIKI  和本文第三部分资料

(以下代码主要讲的使用流程,不保证可直接编译运行)


1,无OS,RAW-api实现

详细使用可参考致远电子这篇pdf资料 

 http://wenku.baidu.com/view/250d6fd3240c844769eaee6c.html


更多RAW-API实例  http://www.ultimaserial.com/classroom2.html

实例1  http://www.ultimaserial.com/avr_lwip_tcp.html

实例2

lwIPInit(pucMACArray, inet_addr("10.0.0.10"), inet_addr("255.255.255.0"), inet_addr("10.0.0.1"), IPADDR_USE_STATIC || IPADRR_USE_DHCP);

but this uses also the auto_ip after the DHCP times-out.

void ethernet_init(void){
    struct tcp_pcb *pcb;
    struct ip_addr ipaddr;
    u16_t port;

    pcb = tcp_new();
    IP4_ADDR(&ipaddr,  10, 0, 0, 2);
    port=5001;
    
    tcp_err(pcb, ethernet_error);
    err=tcp_connect(pcb, &ipaddr, port, ethernet_send);
    if (err != ERR_OK)
    {
        while(1);
    }
}

err_t ethernet_send(void *arg, struct tcp_pcb *pcb, err_t err){
unsigned int len;

    usprintf(data,"Meetwaarde: \n %d", value);

    tcp_sent(pcb, ethernet_received);

    len=strlen(data);
    err=tcp_write(pcb, data, len, 0);
                                               
    if (err != ERR_OK)
    {
        while(1);
    }
    return ERR_OK;
}

err_t ethernet_received(void *arg, struct tcp_pcb *tpcb, u16_t len){
    tempCalc=len;
    err=tcp_close(tpcb);
    newDat=true;
    return ERR_OK;
}

void ethernet_error(void *arg, err_t err){
//    Error just wait here
    value=err;
    while(1);
}




2,有OS,netconn-API实现

1、struct netconn * netconn_new(enum netconn_type type)
创建一个新连接,返回netconn结构体。参数为连接类型,仅应为这两种格式之一:NETCONN_TCP和NETCONN_UDP。
2、void netconn_delete(struct netconn * conn)
断开连接,释放conn结构体。
3、enum netconn_type netconn_type(struct netconn * conn)
返回协议类型,与netconn_new()的函数参数一样,仅有NETCONN_TCP和NETCONN_UDP两种。
4、int netconn_peer(struct netconn * conn, struct ip_addr ** addr, unsigned short * port)
这个函数获得与远端机连接的IP地址填充在“addr”结构体指针中,和端口号填充在“port”中。在未建立连接时,该函数获取值不可预料。
5、int netconn_addr(struct netconn * conn, struct ip_addr ** addr, unsigned short * port)
这个函数获取本地IP地址和端口号,与上面函数相似。
6、int netconn_bind(struct netconn * conn, struct ip_addr * addr, unsigned short port)
将“conn”连接与本地IP地址和端口号捆绑起来。若IP地址为NULL,则默认系统自定义的IP地址。
7、int netconn_connect(struct netconn * conn, struct_ip addr * remote_addr, unsigned short remote_port)
若为UDP协议,设置远端机IP地址和端口号并建立一个连接;若为TCP协议,建立一个远端主机连接。
8、int netconn_listen(struct netconn * conn)
TCP协议专用:将TCP连接设置为监听状态。
9、struct netconn * netconn_accept(struct netconn * conn)
TCP协议专用:等待一个从远端主机发出的链接请求,“conn”连接必须处于监听状态,即必须事先调用完netconn_listen()函数。主机发出连接请求并成功响应后,会返回一个新连接netconn结构体。
10、struct netbuf * netconn_recv(struct netconn * conn)
等待一个连接上接收到数据,如果连接已经被远端主机断开,返回NULL,否则返回数据包到netbuf结构体中。
11、int netconn_write(struct netconn * conn, void * data, int len, unsigned int flags)
TCP协议专用:将“data”指向的数据送入TCP连接的发送队列中并发送。发送数据的长度是“len”字节数,长度不受限制。“flags”只能由两个值:
#define NETCONN_NOCOPY 0x00
#define NETCONN_COPY   0x01
NETCONN_COPY表示“data”数据被复制到内部缓存中,这样“data”中的数据便可以在调用这个函数后被修改,但是由于每次发送都需要复制,效率变低,内存需求增加;NETCONN_NOCOPY表示“data”中数据不被复制到内部而是直接使用,这样“data”中的数据在调用这个函数后也不能被修改,知道这个数据被成功发送出去后才可以被修改。这适用于数据存放在ROM中的情况。
12、int netconn_send(struct netconn * conn, struct netbuf * buf)
UDP协议专用:将netbuf结构体中指向的数据通过UDP协议的连接发送出去。netbuf结构体中的数据由IP帧格式的限制而不能太多,不能超过1000字节。数据大小在函数中并不检验,发送过大的包会产生不可预知的后果。
13、int netconn_close(struct netconn * conn)
断开连接“conn”。



简单实例1

First, you have to enable timeouts by setting:

#define LWIP_SO_RCVTIMEO 1

Then you have to set up your netconn similarly to this:

pxTCPListener = netconn_new (NETCONN_TCP);

netconn_bind (pxTCPListener, NULL, 23);

netconn_listen (pxTCPListener);

pxNewConnection = netconn_accept (pxTCPListener); //This blocks until connection is accepted

//This is the important line!

pxNewConnection->recv_timeout = 10; //note This is millseconds - lwip works in ms

//This loops until the connection is closed

while(!ERR_IS_FATAL(pxNewConnection->err)) { //Fatal errors include connections being closed, reset, aborted, etc

//This netconn_recv call will now wait 10ms for any new data, then return

if ((pxRxBuffer = netconn_recv (pxNewConnection)) != NULL) {

//Handle received data

}

//Here, do any transmits you want

} //End of while loop from above



简单实例2  TCP 客户端

void vTestClient( void *pvParameters )
{
(void) pvParameters; // Satisfy complier
struct netconn *conn;
struct netbuf *inBuf;
char pageData[1024];
char getText[]="GET / HTTP/1.1\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 1.0.3705)\r\nHost: www.YourWebsite.com\r\nConnection: Keep-Alive\r\n\r\n";
int length, bindErr, connErr, writeErr;
u16_t port;
struct ip_addr remoteIP;


while(true)
{
// Create a new socket... API will always create socket 0??
conn = netconn_new(NETCONN_TCP);
// There is only one other possible socket open.
conn->socket = 1; 
remoteIP.addr = IP_ADDRESS(--,--,--,--);
connErr = netconn_connect(conn,&remoteIP,80);
debug_printf("connErr = %d\n",connErr);
if(conn != NULL && connErr == 0)
{
writeErr = netconn_write(conn,&getText,sizeof(getText),NETCONN_NOCOPY);
inBuf = netbuf_new();
while((inBuf = netconn_recv(conn)) != NULL)
{
do
{
netbuf_data(inBuf,&pageData,&length); 
}
while(netbuf_next(inBuf)>=0);
}
if(inBuf != NULL) netbuf_delete(inBuf);
}
if(conn != NULL)
{
while(netconn_delete(conn) != ERR_OK)
{
vTaskDelay(webSHORT_DELAY);
}
}
debug_printf("Sleep\n");
Sleep(300000);
}

实例 3 TCP  UDP

http://www.amobbs.com/thread-5059971-1-1.html
UDP 
{
        static struct netconn *conn;
        static struct netbuf  *UDPNetbuf;
        static struct ip_addr *addr;
        static struct ip_addr destip; 
        static unsigned short port;        
        unsigned char Array[50];
        char *pTemp;
        int DataLen;

        conn = netconn_new(NETCONN_UDP);       /* 创建UDP连接  */

        netconn_bind(conn, IP_ADDR_ANY, 23);

        while(1)
        {
                UDPNetbuf = netconn_recv(conn);                                //接受数据

                addr = netbuf_fromaddr(UDPNetbuf); 
                port = netbuf_fromport(UDPNetbuf);
                destip = *addr;


            netconn_connect(conn, &destip, port);

                netbuf_copy(UDPNetbuf, Array, UDPNetbuf->p->tot_len);

                Array[UDPNetbuf->p->tot_len] = '\0';

            UDPNetbuf->addr=&destip;

        UDPNetbuf->port=port;

            netconn_send(conn, UDPNetbuf);

        netbuf_delete(UDPNetbuf);
        }        
}



这个是TCP的
{
    struct netconn *conn, *newconn = NULL;
    struct netbuf        *TCPNetbuf;
    
        UARTprintf("TCP_Test_task\n");

    conn = netconn_new(NETCONN_TCP);      /* 创建TCP连接  */
    
    netconn_bind(conn,NULL,80);           /* 绑定本地地址和监听的端口号 */
    
    netconn_listen(conn);                 /* 进入监听状态 */
    while(1)
    {
      newconn = netconn_accept(conn);    /*阻塞当前进程到有数据接收 */
      if(newconn != NULL)
      {    
            if((TCPNetbuf = netconn_recv(newconn)) != NULL)
            {
                
                netconn_write(newconn,(void *)http_html_hdr,sizeof(http_html_hdr),NETCONN_NOCOPY);
                                           /* 发送头部数据  */
                netconn_write(newconn,(void *)indexdata,sizeof(indexdata),NETCONN_NOCOPY);
                                           /* 发送实际的WEB页面 */
                                
                netbuf_delete(TCPNetbuf);
            }          
            netconn_close(newconn);       /* 关闭连接   */
            
          while(netconn_delete(newconn) != ERR_OK)
            OSTimeDlyHMSM(0, 0, 1, 0);
      }
    }
}




3,有OS,socket实现


第一步lwip初始化

#include  "lwip/ip_addr.h"
#include	"lwip/netif.h"
#include	"lwip/tcpip.h"
#include "netif/etharp.h"
#include "lwip/init.h"

#include "inc/hw_ethernet.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "driverlib/interrupt.h"
#include "driverlib/ethernet.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/debug.h"

unsigned char MACAddress[]={0X00,0x14,0x97,0x0F,0x1D,0xE3};

struct netif lwip_netif;

void my_lwip_init(void)
{
   extern err_t stellarisif_init(struct netif *netif);
   extern struct netif lwip_netif;
   struct ip_addr ipaddr, netmask, gw;
   
   SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);    /* 复位并使能以太网控制器*/
   SysCtlPeripheralReset(SYSCTL_PERIPH_ETH);
    
   SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);  /* 使能以太网控制器的指示灯*/
   GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3, GPIO_DIR_MODE_HW);
   GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3,
                     GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
   //IntMasterEnable();                                          //使能总的中断
   
   SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);                    //使能以太网控制器

    EthernetMACAddrSet(ETH_BASE, (unsigned char *)&MACAddress[0]);       //编程以太网控制器的MAC地址
   
   tcpip_init(NULL, NULL);
   
   IP4_ADDR(&ipaddr, 192,168,41,163);
   IP4_ADDR(&netmask, 255,255,255,0);
   IP4_ADDR(&gw, 192,168,41,254);
   
   netif_add(&lwip_netif, &ipaddr, &netmask, &gw, NULL, stellarisif_init, tcpip_input);
   netif_set_default(&lwip_netif);
   netif_set_up(&lwip_netif);
   
   IntPrioritySet(INT_ETH, 0xFF);    /*设置以太网中断优先级*/
   /* Enable Ethernet TX and RX Packet Interrupts. */
   EthernetIntEnable(ETH_BASE, ETH_INT_RX | ETH_INT_TX);
   /* Enable the Ethernet Interrupt handler. */
   IntEnable(INT_ETH);
}


第二步:调用下面的任务

#include "lwip/opt.h"
#include "lwip/sys.h"
#include "lwip/sockets.h"
#include "string.h"

unsigned char HTTP_GET_STRING[]                      =           \
                        "GET";
#define HTTP_GET_STRING_LEN                                 \
                        (sizeof(HTTP_GET_STRING)-1)
unsigned char htmldata[] = "	\
<html>	\
	<head> 	\
		<title>这是个测试文件</title>\
	</head>	\
	<body>	\
		uCOS-II v2.86 & Lwip v1.3.0 HELLO WORLD!\
	</body>\
	</html>";
	
void httpd_thread(void *arg)
{
	int s, ei, temp;

	struct sockaddr_in serv, cli;
		
	
	memset(&serv, 0, sizeof(struct sockaddr_in));
	serv.sin_family = AF_INET;
	serv.sin_port = htons(80);	
	serv.sin_addr.s_addr = htons(INADDR_ANY);
	
	
	s = socket(AF_INET, SOCK_STREAM, 0);
	
	ei = bind(s, (struct sockaddr*)&serv, sizeof(struct sockaddr_in));
    ei = listen(s, 5);
    
    while (1)
    {
    	u32_t len;
    	INT8U cmd[4];
    	temp = accept(s, (struct sockaddr*)&cli, &len);
    	if (temp != -1)
    	{
    		recv(temp, cmd, HTTP_GET_STRING_LEN, 0);
    		cmd[3] = 0;
    		
    			
    		send(temp, htmldata, sizeof(htmldata), 0);
    	}
    	close(temp);
        //OSTimeDlyHMSM(0, 0, 0, 50);
    }
 }





第五部分其他

1,常用代码托放网站 

更详细可参考   http://en.wikipedia.org/wiki/Comparison_of_open_source_software_hosting_facilities

GitHub(推荐)

Sourceforge

Google Code (被q容易打不开)

Gitorious

Microsoft's CodePlex

2,TCP坚持与保活http://blog.sina.com.cn/s/blog_62a85b950101aw8x.html


http://blog.gkong.com/more.asp?id=154809&Name=john1225cn

成功实现了LWIP的keepalive功能

成功实现了LWIP的keepalive功能

原来的lwip没有启动keepalive功能,导致tcp客户端工作不可靠,主要就是无法处理服务器的断线、断网、down机等异常。表现是服务器故障后,tcp客户端总是等待无法返回,造成锁死。

处理方法:

1,使用TCPkeepalive功能,定时探测连接的状态,当发生掉线时,自动关闭连接,正常返回。

2,检测网线状态PHY寄存器中有标准位。(没有上一种方法好。)

下面详细介绍如何启动keepalive

1,打开keepalive的标志使能。

2,修改keepalive各个计数值,主要是改小,方便测试。

3,在pcb中需要置位keepalive的一个选项。pcb->so_options |= SOF_KEEPALIVE;

4,修改pcb的一处bug,该bug可以通过给我汇款获得。

启动了keepalive才是真正的tcp连接,用起来稳定可靠,异常爽快。


3

LwIP中采用netcon接口进行异步读写

http://wenku.baidu.com/view/e6e44f4b2e3f5727a5e962dc.html

http://www.rt-thread.org/phpBB3/viewtopic.php?q=phpbbforum/viewtopic.php&f=2&t=277


4 LWIP netconn函数讲解以及实例

http://blog.csdn.net/ysdaniel/article/details/6646801



  • 1
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值