搜索
bottom↓
回复: 12

关于ucos+lwip的问题

[复制链接]

出0入0汤圆

发表于 2009-12-28 14:31:50 | 显示全部楼层 |阅读模式
最近在做一个项目,平台式UCOSII+LWIP
大体上接近完成,有几个小问题,比较困惑,向大虾们请教
1:我的实现是用LWIP做server端,但是当链接断开后,必须重启设备才可以重新链接,为何?
2:select的实现始终有问题,select始终处于阻塞状态,后面的程序得不到运行,直接使用recv和send接收发送数据则没有问题?

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2009-12-28 15:20:52 | 显示全部楼层
1估计是listen那边没有做循环的原因?(断开后没会到listen处?)
2select需要设置一个超时时间,不知道楼主设了没有?

出0入168汤圆

发表于 2009-12-28 15:28:18 | 显示全部楼层
回复【1楼】kanprin  
-----------------------------------------------------------------------

请问select是如何用的?

出0入0汤圆

 楼主| 发表于 2009-12-28 17:31:21 | 显示全部楼层
回复【1楼】kanprin  
1估计是listen那边没有做循环的原因?(断开后没会到listen处?)
2select需要设置一个超时时间,不知道楼主设了没有?

-----------------------------------------------------------------------
首先感谢回复

1:程序有两个循环,链接建立后应该处于收发应用的循环中,如果断开连接了,会给sock置-1,然后进行socket bind listen的循环,所以断开后应该会运行listen(刚刚又试验了下,如果主动的点击断开链接,则可以重新连上,如果是收发数据过程中出现异常导致链接断开,则连不上了,我想这时可能程序一直阻塞在recv,导致无法连上)

2:select超时时间设了,和没设一个效果。。

出0入0汤圆

发表于 2009-12-28 18:15:31 | 显示全部楼层
可否把程序共享一下,大家一起研究下?

出0入168汤圆

发表于 2009-12-28 18:36:45 | 显示全部楼层
回复【3楼】emperorgerrard  
-----------------------------------------------------------------------

能否把select应用部分的代码贴上来?

出0入0汤圆

 楼主| 发表于 2009-12-28 19:47:58 | 显示全部楼层
整个代码就不放上来了,因为是公司的产品,里面已经添加了很多的驱动和应用,避免纠纷
如果对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;
        }
}

出0入0汤圆

发表于 2009-12-29 08:47:48 | 显示全部楼层
回复【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之前再设置,即每次调用都要设(如果我没记错的话)。

出0入0汤圆

发表于 2009-12-29 10:00:55 | 显示全部楼层
你的硬件环境是什么环境呢?STM32的吗?

出0入0汤圆

 楼主| 发表于 2009-12-29 10:18:59 | 显示全部楼层
回复【8楼】arm_love  
你的硬件环境是什么环境呢?STM32的吗?
-----------------------------------------------------------------------

硬件环境是LPC2468,PHY是RTL8201CP

TCP断开不能重连的问题,我还是觉得程序阻塞在了recv或者send(在网上下的网络调试助手,估计其运行过程中异常断开,而服务器端没有接收到断开的信号,因此仍然认为连接存在而进行收发操作,阻塞在了收发函数)。如果我主动的断开连接,那么重新连接是没有问题了

select的问题,添加wfds后,发送的复用貌似可以,但是接收不行,头大。。

出0入0汤圆

发表于 2009-12-30 19:30:28 | 显示全部楼层
关注

出0入0汤圆

发表于 2010-7-10 10:36:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-12 10:22:15 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-13 15:08

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表