请教RT-Thread中LWIP Socket编程?
老规矩,自报家门STM32F207IGT6 MDK RTT 1.1.0 LWIP
声明:对于文中引用的文字,如果有侵犯到您权益,请您通知我,我会第一时间删除,谢谢!
LwIP为我们提供了两种API函数来实现TCP/IP协议栈,它们分别是:
1、low-level "core" / "callback" or "raw" API. ——低水平的、基于回调函数的API(后面直接称RAW API)
2、higher-level "sequential" API.——高水平的、连续的API(后面直接称sequential API)
问题1:请问在RT-Thread使用的是哪种API 呢?
我们新手通常会使用connect、 accept、recv或recvfrom这样的阻塞程序,但是使用阻塞程序后会降低程序的效率,有的前辈提出使用selet()这个非阻塞程序来提高程序的效率。
先提一下select的函数原型
int select( int maxfdp,
fd_set *readfds,
fd_set *writefds,
fd_set *errorfds,
struct timeval *timeout);
maxfdp:所有文件描述符的最大值加1
*readfds:要监视这些文件描述符的读变化
*writefds:要监视这些文件描述符的写变化
*timeout:select的超时时间
返回值:
负值:select错误
正值:某些文件可读写或出错
0:等待超时,没有可读写或错误的文件
部分程序:
int listenfd;
struct sockaddr_in saddr;
fd_set readset;
listenfd = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if( listenfd == -1 )
{
rt_kprintf("TCP setup can not create socket!\n");
return;
}
memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(SETUP_TCP_PORT);
if( lwip_bind(listenfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1 )
{
lwip_close(listenfd);
rt_kprintf("TCP setup thread socket bind failed!\n");
return;
}
/* Put socket into listening mode */
if (lwip_listen(listenfd,2) == -1)
{
lwip_close(listenfd);
rt_kprintf("Listen failed.\n");
return;
}
/* Wait for data or a new connection */
while(1)
{
/* Determine what sockets need to be in readset */
FD_ZERO(&readset);
FD_SET(listenfd, &readset);
// wait forever.
if( lwip_select(listenfd+1, &readset, 0, 0, 0) == 0 )
continue;
if (FD_ISSET(listenfd, &readset))
{
……………..
数据接收处理
}
}
这段代码是RTT开源产品—“以太网转串口”中tcp_setup_thread的,首先感谢Mbbill前辈的无私奉献
将红色这段代码直接改成
if( lwip_select(listenfd+1, &readset, 0, 0, 0) == 0 )
{
continue;
}
else if(lwip_select(listenfd+1, &readset, 0, 0, 0) > 0)
{
……………..
数据接收处理
}
else
{
break;
}
问题2:程序修改后可以运行,但是请问这样修改会不会有不妥的地方呢?
RTT开源产品—“以太网转串口”中的tcp_setup_thread程序疑问
先提一下recv的函数原型
int recvfrom(int sockfd,
void *buf,
int len,
unsigned int flags,
struct sockaddr *from,
socket_t *fromlen);
recv() 和 recvfrom()功能相同
参数:
sockfd:标识一个已连接套接口的描述字。
buf:接收数据缓冲区。
len:缓冲区长度。
flags:调用操作方式。
from:(可选)指针,指向装有源地址的缓冲区。
fromlen:(可选)指针,指向from缓冲区长度值。
返回值:
正确接收返回接收到的字节数,失败返回0.
#define P2X_HEADER_LEN (14)
/*********************** 代码段1 ****************************/
……..已成功建立连接
while(1)
{
int dataLen,bytesRet;
ret = blocking_lwip_recv(socket,
setup_data_buf,
P2X_HEADER_LEN,
500);
if( ret == 0 )
continue;
if( ret != P2X_HEADER_LEN )
break;
dataLen = P2X_GET_LENGTH(setup_data_buf);
if( dataLen > 0 )
{
int gotDataLen=blocking_lwip_recv(socket,
setup_data_buf+P2X_HEADER_LEN,
dataLen,
500);
if( gotDataLen != dataLen )
break;
}
bytesRet = processCMD(setup_data_buf,P2X_HEADER_LEN+dataLen);
if( lwip_send(socket,setup_data_buf,bytesRet,0) < 0 )
break;
}
/*********************** 代码段2****************************/
int blocking_lwip_recv(int s, void *mem, size_t len, int timeout)
{
int readlen, offset = 0;
fd_set fds;
int ret;
struct timeval to;
to.tv_sec = timeout/1000;
to.tv_usec = (timeout%1000)*1000;
while(1)
{
FD_ZERO(&fds);
FD_SET(s,&fds);
ret = lwip_select(s+1,&fds,0,0,&to);
if( ret == 0 )
break;
else if( ret < 0 )
return ret;
readlen = lwip_recvfrom(s, ((char*)mem)+offset, len-offset, 0, NULL, NULL);
if( readlen == 0 )
return -1;
else if( readlen < 0 )
return readlen;
if( readlen == (len-offset) )
{
offset = len;
break;
}
offset += readlen;
}
return offset;
}
代码段1调用代码段2中 blocking_lwip_recv()函数,并且给了超时时间,在blocking_lwip_recv()中也调用了select函数,同时增加了500ms的超时判断。那么就有2种情况:
1、 没有数据,超时溢出,跳出进行下一次等待(我能理解)
2、 接收到数据,也有readlen长度的数据
问题3:对于代码段1中
if( ret != P2X_HEADER_LEN )
break;
为什么要进行这个判断?我自己的理解是它在进行通信时自己添加了一个头“P2X_HEADER”,但是我手上没这个板子,没法验证。
问题4:select()函数的超时判断的时间是依据什么来设置的呢?
问题5:关于代码段2中的超时时间,网上有篇博客提到了超时时间是否每次都需要初始化,小弟对linux内核不懂,请问在lwip中是否也是一样呢?
http://xingyunbaijunwei.blog.163.com/blog/static/76538067201221094057503/
参考1:我觉得blocking_lwip_recv()中的timeout参数可以分成timeout_second,timeout_ microsecond,这样或许更清楚一点,呵呵!
可以先买本《Linux网络编程(Linux典藏大系)》或类似的书:
当当链接:http://product.dangdang.com/main/product.aspx?product_id=20750208 aozima 发表于 2013-1-8 13:44 static/image/common/back.gif
可以先买本《Linux网络编程(Linux典藏大系)》或类似的书:
当当链接:http://product.dangdang.com/main/ ...
嗯,好的!aozima版主,这个以太网转串口开源产品还有讨论的板块吗?以前那个都关闭了 楼主你好,我也出现了你的情况,,,,TCP链接不连接,UDP都是可以的 zhangpisces 发表于 2013-3-21 15:01 static/image/common/back.gif
楼主你好,我也出现了你的情况,,,,TCP链接不连接,UDP都是可以的
什么现象,用抓包看看 Baldwin 发表于 2013-3-21 15:19 static/image/common/back.gif
什么现象,用抓包看看
抓出来好像就是没有应答 zhangpisces 发表于 2013-3-21 15:52 static/image/common/back.gif
抓出来好像就是没有应答
握手能成功吗
页:
[1]