关于ucos+lwip的问题
最近在做一个项目,平台式UCOSII+LWIP大体上接近完成,有几个小问题,比较困惑,向大虾们请教
1:我的实现是用LWIP做server端,但是当链接断开后,必须重启设备才可以重新链接,为何?
2:select的实现始终有问题,select始终处于阻塞状态,后面的程序得不到运行,直接使用recv和send接收发送数据则没有问题? 1估计是listen那边没有做循环的原因?(断开后没会到listen处?)
2select需要设置一个超时时间,不知道楼主设了没有? 回复【1楼】kanprin
-----------------------------------------------------------------------
请问select是如何用的? 回复【1楼】kanprin
1估计是listen那边没有做循环的原因?(断开后没会到listen处?)
2select需要设置一个超时时间,不知道楼主设了没有?
-----------------------------------------------------------------------
首先感谢回复
1:程序有两个循环,链接建立后应该处于收发应用的循环中,如果断开连接了,会给sock置-1,然后进行socket bind listen的循环,所以断开后应该会运行listen(刚刚又试验了下,如果主动的点击断开链接,则可以重新连上,如果是收发数据过程中出现异常导致链接断开,则连不上了,我想这时可能程序一直阻塞在recv,导致无法连上)
2:select超时时间设了,和没设一个效果。。 可否把程序共享一下,大家一起研究下? 回复【3楼】emperorgerrard
-----------------------------------------------------------------------
能否把select应用部分的代码贴上来? 整个代码就不放上来了,因为是公司的产品,里面已经添加了很多的驱动和应用,避免纠纷
如果对lwip和UCOSII的移植什么想共同研究的话,可以加我GTALK,yuqinjuve@gmail.com(或者直接发邮件也可)
可以把移植部分的代码及个人的理解分享。
其实我也是个菜鸟。
select的应用,我的应用是注释掉的那段,因为要测试移植的稳定性,所以我先注释掉测试了
int ret;
int sockFd = -1;
int connectFd = -1;
volatile int maxFd;
int opt;
uint32 len;
int tcpPort = 7777;
int recvNum;
int sendNum;
struct sockaddr_in svrAddr,cltAddr;
fd_set rfds;
fd_set wfds;
struct timeval timeOut;
parg = parg;
timeOut.tv_sec = 5;
timeOut.tv_usec = 0;
svrAddr.sin_family = AF_INET;
svrAddr.sin_port = htons(tcpPort);
svrAddr.sin_addr.s_addr = htons(INADDR_ANY);
while (1)
{
sockFd = socket( AF_INET, SOCK_STREAM, 0 );
if ( sockFd < 0 )
{
continue;
}
ret = bind( sockFd, (struct sockaddr *)&svrAddr, sizeof(svrAddr) );
if ( ret < 0 )
{
lwip_close(sockFd);
sockFd = -1;
continue;
}
ret = listen( sockFd, 1 );
if ( ret < 0 )
{
lwip_close(sockFd);
continue;
}
len = sizeof(cltAddr);
connectFd = accept( sockFd, (struct sockaddr *)&cltAddr, &len );
if ( -1 != connectFd )
{
opt = 1;
send( connectFd, "Start TCP Server\r", 17, 0 );
}
maxFd = connectFd;
while (-1 != connectFd)
{
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET( connectFd, &rfds );
FD_SET( connectFd, &wfds );
//maxFd = connectFd;
recvNum = recv( connectFd, tcpBuf, 20, 0 );
if ( recvNum <= 0 )
{
lwip_close(connectFd);
connectFd = -1;
break;
}
sendNum = send( connectFd, tcpBuf, 20, 0 );
OSTimeDly(100);
/*ret = lwip_select( connectFd+1, &rfds, NULL, NULL, &timeOut );
if ( ret < 0 )
{
lwip_close(connectFd);
connectFd = -1;
break;
}
else if ( 0 == ret )
{
continue;
}
else
{
if ( FD_ISSET( connectFd, &rfds ) )
{
recvNum = recv( connectFd, tcpBuf, 20, 0 );
if ( recvNum <= 0 )
{
lwip_close(connectFd);
connectFd = -1;
break;
}
}
}*/
}
lwip_close(sockFd);
sockFd = -1;
}
} 回复【6楼】emperorgerrard
-----------------------------------------------------------------------
端口绑定和侦听只需做一次即可,
接下来只要调用accept就能收到你连接的socket了。
即
...
...
while(1)
{
socket();
bind();
listen();
while(1)
{
//非阻塞加入select(),阻塞方式直接调用accept();
connectFd = accept( sockFd, (struct sockaddr *)&cltAddr, &len );
//接下来看你是先收数据recv()还是先发数据send()
while(1)
{ //直接调用recv也是阻塞方式,要用非阻塞方式,必须加入到select()中
recvNum = recv( connectFd, tcpBuf, 20, 0 );
if ( recvNum <= 0 )
{
break;
}
sendNum = send( connectFd, tcpBuf, 20, 0 );
OSTimeDly(100);
}
lwip_close(connectFd);//close()后直接返回到accept即可,不需要重新绑定与侦听
}
}
回复【2楼】eiglxl
-----------------------------------------------------------------------
请问select是如何用的?
-----------------------------------------------------------------------
FD_ZERO(&ntrds);//用select函数之前先把集合清零
FD_SET(listen_socket1, &ntrds);//把要检测的句柄加入到socket集合里
FD_SET(listen_socket2, &ntrds);//把要检测的句柄加入到socket集合里
if((ret = select(0, &ntrds, (fd_set*)0, (fd_set *)0, NULL)) > 0)
{
if(FD_ISSET(listen_socket1, &ntrds))
{
//侦听端口1有连接,处理
}
if(FD_ISSET(listen_socket2, &ntrds))
{
//侦听端口2有连接,处理
}
}
//此处的select没有加入超时机制,加入超时的方式见6楼的方式,
//不过那个超时时间需要在调用select之前再设置,即每次调用都要设(如果我没记错的话)。 你的硬件环境是什么环境呢?STM32的吗? 回复【8楼】arm_love
你的硬件环境是什么环境呢?STM32的吗?
-----------------------------------------------------------------------
硬件环境是LPC2468,PHY是RTL8201CP
TCP断开不能重连的问题,我还是觉得程序阻塞在了recv或者send(在网上下的网络调试助手,估计其运行过程中异常断开,而服务器端没有接收到断开的信号,因此仍然认为连接存在而进行收发操作,阻塞在了收发函数)。如果我主动的断开连接,那么重新连接是没有问题了
select的问题,添加wfds后,发送的复用貌似可以,但是接收不行,头大。。 关注 mark mark
页:
[1]