emperorgerrard 发表于 2009-12-28 14:31:50

关于ucos+lwip的问题

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

kanprin 发表于 2009-12-28 15:20:52

1估计是listen那边没有做循环的原因?(断开后没会到listen处?)
2select需要设置一个超时时间,不知道楼主设了没有?

eiglxl 发表于 2009-12-28 15:28:18

回复【1楼】kanprin
-----------------------------------------------------------------------

请问select是如何用的?

emperorgerrard 发表于 2009-12-28 17:31:21

回复【1楼】kanprin
1估计是listen那边没有做循环的原因?(断开后没会到listen处?)
2select需要设置一个超时时间,不知道楼主设了没有?

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

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

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

arm_love 发表于 2009-12-28 18:15:31

可否把程序共享一下,大家一起研究下?

eiglxl 发表于 2009-12-28 18:36:45

回复【3楼】emperorgerrard
-----------------------------------------------------------------------

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

emperorgerrard 发表于 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;
        }
}

kanprin 发表于 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之前再设置,即每次调用都要设(如果我没记错的话)。

arm_love 发表于 2009-12-29 10:00:55

你的硬件环境是什么环境呢?STM32的吗?

emperorgerrard 发表于 2009-12-29 10:18:59

回复【8楼】arm_love
你的硬件环境是什么环境呢?STM32的吗?
-----------------------------------------------------------------------

硬件环境是LPC2468,PHY是RTL8201CP

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

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

astudent 发表于 2009-12-30 19:30:28

关注

wunihaoo 发表于 2010-7-10 10:36:57

mark

lou0908 发表于 2010-10-12 10:22:15

mark
页: [1]
查看完整版本: 关于ucos+lwip的问题