原文链接:http://blog.csdn.net/liang890319/article/details/8456794
本文主要搜集了下互联网上关于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
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
3,有OS,socket实现
第一步lwip初始化
第二步:调用下面的任务
第五部分其他
1,常用代码托放网站
更详细可参考 http://en.wikipedia.org/wiki/Comparison_of_open_source_software_hosting_facilities
Sourceforge
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
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