9926|17

10

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

client connect问题 [复制链接]

本人在做LM3S8962作为客户端测试时,遇到个问题,如果TCP测试软件建立服务器后,客户端有可能会等很久才连上来,关掉了这个连接,就再也建立不上与8962的通信。迷惑中,请高手帮帮忙,万分感谢!我的源码如下:

                               //-----------------------------------------------------------------------------
//
// enet_lwip_tcp.c - 一个简单的lwIP tcp通信例程
//
//-----------------------------------------------------------------------------

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "driverlib/ethernet.h"
#include "driverlib/flash.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "utils/lwiplib.h"
#include "utils/uartstdio.h"
#include "utils/truly128x64.h"
#include "utils/ustdlib.h"
#include <LM3Sxxxx.h>

//----------------------------------------------------------------------------
//! 这个例子展示了对Stellaris以太网控制器的使用,通过lwIP TCP/IP 协议栈
//  http://savannah.nongnu.org/projects/lwip/
//----------------------------------------------------------------------------


#define ulPORT  3000

//----------------------------------------------------------------------------
//
// Defines for setting up the system clock.
// 定义systick时钟
//-----------------------------------------------------------------------------
#define SYSTICKHZ               100
#define SYSTICKMS               (1000 / SYSTICKHZ)

unsigned char sent_ok_flag = 0;
struct tcp_pcb *now_pcb;
char tmpbuf[20];
void *ptr;
struct ip_addr ipaddr;

//-----------------------------------------------------------------------------
//
// 显示lwip的IP地址信息函数
//
//-----------------------------------------------------------------------------
void
DisplayIPAddress(unsigned long ipaddr, unsigned long ulCol,
                 unsigned long ulRow)
{
    char pucBuf[16];
    unsigned char *pucTemp = (unsigned char *)&ipaddr;

    //
    // 转换IP地址到字符串
    //
    usprintf(pucBuf, "%d.%d.%d.%d", pucTemp[0], pucTemp[1], pucTemp[2],
             pucTemp[3]);

    //
    //显示字符串
    //
    Oled_Dis_string(ulCol,ulRow,pucBuf);
}
//-----------------------------------------------------------------------------
//
// 被lwIp库使用,用来支持任何主机相关的定时功能
//
//-----------------------------------------------------------------------------
void
lwIPHostTimerHandler(void)
{
    static unsigned long ulLastIPAddress = 0;
    unsigned long ulIPAddress;
    char pucBuf[16];

    ulIPAddress = lwIPLocalIPAddrGet();

    //
    // If IP Address has not yet been assigned, update the display accordingly
    //
    if(ulIPAddress == 0)
    {

    }
    //
    // Check if IP address has changed, and display if it has.
    //
    else if(ulLastIPAddress != ulIPAddress)
    {       
  ulLastIPAddress = ulIPAddress;
  Oled_Dis_string(2,2,"IP:   ");
  Oled_Dis_string(3,2,"MASK: ");
  Oled_Dis_string(4,2,"GW:   ");
  Oled_Dis_string(5,2,"Port: ");
        DisplayIPAddress(ulIPAddress, 2, 38);
        ulIPAddress = lwIPLocalNetMaskGet();
        DisplayIPAddress(ulIPAddress, 3, 38);
        ulIPAddress = lwIPLocalGWAddrGet();
        DisplayIPAddress(ulIPAddress, 4, 38);
  usprintf(pucBuf, "%d", ulPORT);
  Oled_Dis_string(5, 38,pucBuf);
    }
}


//-----------------------------------------------------------------------------
//
// systick中断处理函数
//
//-----------------------------------------------------------------------------
void
SysTickIntHandler(void)
{
    //
    // 调用lwip定时处理函数
    //
    lwIPTimer(SYSTICKMS);
}


//-----------------------------------------------------------------------------
//
// 发送完成回调函数
//
//-----------------------------------------------------------------------------
err_t Sent_Ok(void *arg,struct tcp_pcb *pcb,u16_t err)
{
   tcp_close(pcb);
   return ERR_OK;
}


//-----------------------------------------------------------------------------
//
// 接收到数据的回调函数
//
//-----------------------------------------------------------------------------
err_t recv_now(void *arg,struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
 

   if(p != NULL)                              //如果收到的数据不为空              
   {
    
   tcp_write(tpcb,p->payload,p->len,0);     //将接收到的数据发送出去        
     pbuf_free(p);                            // 释放缓冲区数据
  tcp_recved(tpcb,p->tot_len);
  //tcp_output(tpcb);
   
   }
   return ERR_OK; 
}

//-----------------------------------------------------------------------------
//
// 接受连接请求
//
//-----------------------------------------------------------------------------
err_t TCP_SER_Connected(void *arg, struct tcp_pcb *pcb, err_t err)
  {
 
  //
     // Clear out all of the TCP callbacks.
     //
     tcp_arg(pcb, NULL);
     tcp_sent(pcb, NULL);
     tcp_recv(pcb, NULL);
     tcp_err(pcb, NULL);
     tcp_poll(pcb, NULL, 1);

     //
     // Close the TCP connection.
     //
    tcp_close(pcb);


   tcp_recv(pcb,recv_now);
 
 return(ERR_OK);
}

/*****************************************************************************************
** Function name:       TCP_SER_Poll
** Descriptions:        接收处理函数
** input parameters:    无
** output parameters:   无
** Returned value:      无
*****************************************************************************************/
 err_t TCP_SER_Poll(void *arg, struct tcp_pcb *pcb)
 {
    err_t eError;


 eError = tcp_connect(pcb, &ipaddr, ulPORT, TCP_SER_Connected);

 if(eError != ERR_OK)
    {
       
        return 1;
    }
     return 0;
  }


/*****************************************************************************************
** Function name:       TCP_Client_Init
** Descriptions:        客户端模式初始化网络连接
** input parameters:    ulIPAddr
** output parameters:   无
** Returned value:      无
*****************************************************************************************/ 
 void TCP_Client_Init(unsigned long ulIPAddr)
  {
 struct tcp_pcb *local_pcb;
 

    err_t eError;


 ipaddr.addr = htonl(ulIPAddr);

    local_pcb = tcp_new();                      
  tcp_poll(local_pcb, TCP_SER_Poll, (3000 / TCP_SLOW_INTERVAL));
   eError = tcp_connect(local_pcb, &ipaddr, ulPORT, TCP_SER_Connected);
 if(eError != ERR_OK)
    {
       
        return;
    }
   
   }

 


//-----------------------------------------------------------------------------
//
// 使用以太网控制器的一个例子
//
//-----------------------------------------------------------------------------
int
main(void)
{
    unsigned long ulUser0 = 0x12345678, ulUser1 = 0x12345678 ;
    unsigned char pucMACArray[8];
    unsigned long ulIPAddr,ulIPMask,ulIPGateWay,ulIPAddrR;
    //
    //设定系统时钟8MHZ
    //
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_8MHZ);

    //
    // 初始化 OLED 显示.
    //
    Oled_Init();
    Oled_Dis_string(1,10,"Enet lwip Tcp Test");
 

    //
    // 使能以太网控制器,然后复位以太网控制器
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);
    SysCtlPeripheralReset(SYSCTL_PERIPH_ETH);
 SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // 使能端口F来作为以太网的LED使用
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinConfigure(GPIO_PF2_LED1);
    GPIOPinConfigure(GPIO_PF3_LED0);
    GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3);
 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);                 //使能Uart时钟 
    GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_0 | GPIO_PIN_1);    //配置引脚为Rx、Tx功能 
 
 //
 //配置UART0
 //
 UARTConfigSetExpClk(UART0_BASE,SysCtlClockGet(),9600,
    UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE);
                                                               //配置为9600,8位,1个停止位,无校验
   UARTIntEnable(UART0_BASE,UART_INT_RT | UART_INT_RX);         //使能接收中断和接受超时中断
   UARTEnable(UART0_BASE);                                      //启动Uart
 
   IntEnable(INT_UART0);                                        //使能Uart中断

    //
    // 配置systick
    //
    SysTickPeriodSet(SysCtlClockGet() / SYSTICKHZ);
    SysTickEnable();
    SysTickIntEnable();

    //
    //使能处理器中断
    //
    IntMasterEnable();

    //
    //从用户寄存器中 读取MAC地址
    //
    //ROM_FlashUserGet(&ulUser0, &ulUser1);
    if((ulUser0 == 0xffffffff) || (ulUser1 == 0xffffffff))
    {
        //
        // MAC没有编程
        //
        Oled_Dis_string(5,5,"MAC Not Programmed!");
        while(1)
        {
        }
    }

    //
    //转换用户寄存器到MAC地址
    //
    pucMACArray[0] = ((ulUser0 >>  0) & 0xff);
    pucMACArray[1] = ((ulUser0 >>  8) & 0xff);
    pucMACArray[2] = ((ulUser0 >> 16) & 0xff);
    pucMACArray[3] = ((ulUser1 >>  0) & 0xff);
    pucMACArray[4] = ((ulUser1 >>  8) & 0xff);
    pucMACArray[5] = ((ulUser1 >> 16) & 0xff);

    //
    // 初始化lwIP协议栈  静态IP
 // IP地址:   192.168.14.20
    // 子网掩码:255.255.255.0
 // 默认网关:192.168.14.254
    ulIPAddr = (((unsigned long )192<<24)|(168<<16)|(2<<8)|20);
 ulIPMask = ((unsigned long )255<<24)|(255<<16)|(255<<8)|0;
 ulIPGateWay = ((unsigned long )192<<24)|(168<<16)|(2<<8)|254;
 ulIPAddrR = (((unsigned long )192<<24)|(168<<16)|(2<<8)|6);
    lwIPInit(pucMACArray, ulIPAddr,
                       ulIPMask,
        ulIPGateWay, IPADDR_USE_STATIC);

 //
 //初始化客户端TCP
 //
 TCP_Client_Init(ulIPAddrR);

    //
    // 主循环
    //
    while(1)
    {
    }
}

enet_lwip_tcp.rar

1.7 MB, 下载次数: 183

最新回复

tcp_bind这个也不用了吗?  详情 回复 发表于 2011-4-10 11:06
 
点赞 关注(1)

回复
举报

72

帖子

0

TA的资源

一粒金砂(中级)

沙发
 

一个明显的错误

pbuf_free(p); p释放完了,

 tcp_recved(tpcb,p->tot_len); 这句话怎么解释?

p->tot_len在此时是什么值了

[ 本帖最后由 h0nly_zhang 于 2011-3-15 16:03 编辑 ]
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
原帖由 h0nly_zhang 于 2011-3-15 16:00 发表 pbuf_free(p); p释放完了,  tcp_recved(tpcb,p->tot_len); 这句话怎么解释? p->tot_len在此时是什么值了
没问题的。p是在recved时,申请的。
 
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

4
 
据说LWIP无法用来做客户端。
 
 
 

回复

2641

帖子

0

TA的资源

五彩晶圆(中级)

5
 

回复 4楼 ebuffalo 的帖子

不是的,我的LWIP服务器、客服端、TCP\UDP通通都没有问题
 
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

6
 
https://bbs.eeworld.com.cn/viewth ... 25&page=1#pid819892

有新进展了么?LS在上面的帖子中不是说自己写了个协议栈了事。
 
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

7
 
LM3S8962+LWIP通信问题
我开了2个TCPIP通信,一个作为TCPIP CLIENT连接计算机服务器,一个作为TCPIP SERVER作为WEB服务器,查看模块设置信息等,现在的问题是当计算机服务关闭时,TCPIP CLIENT不停的重连接服务器,这时访问TCPIP SERVER的WEB服务器,有一半左右的可能系统死机,调试查看系统进入FaultISR中断,请教是什么原因引起的??如何解决??非常感谢!!!
如果TCPIP CLIENT连接计算机服务器正常,访问TCPIP SERVER的WEB服务器就没有问题
 
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

8
 
上面是风版主发的一个帖子,上面帖子中的问题解决了么?
 
 
 

回复

10

帖子

0

TA的资源

一粒金砂(初级)

9
 
还是一头雾水,感觉跟tcp_arg(),tcp_poll()有关,现在在找这两个函数的资料,从源代码上看不出这两个函数的功能,查了RAW中函数的中文注释,就一两句话带过,望有高手指点
 
 
 

回复

105

帖子

0

TA的资源

一粒金砂(中级)

10
 
问题出在这句函数调用: tcp_close(pcb);  // 这句话是你关闭了连接,所以下次通信就要重新连接!


 
 
 

回复

105

帖子

0

TA的资源

一粒金砂(中级)

11
 

原帖由 ebuffalo 于 2011-3-15 17:13 发表 据说LWIP无法用来做客户端。

 

纯属胡说!!

 
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

12
 
原帖由 历史的天空 于 2011-3-16 22:06 发表   纯属胡说!!
ourdev上,有个帖子讨论过这个问题,几个做开源RTT操作系统的高手也有讨论,LWIP用作客户端,在特定情况下确实有问题,并且,这几位高手也没有找到解决办法。
 
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

13
 
搞死LWIP的方法
RT-Thread核心开发、使用讨论

版主: bernard  

发表回复4 篇帖子 • 分页: 1 / 1  
搞死LWIP的方法
由 mbbill » 2010年 4月 18日 03:29  

lwip的netconn有一个缺陷,它的tcp window和输入缓冲区没有直接联系,输入的数据是以pbuf的形式存放在conn->recvmbox里面的,这个mbox尺寸是10,这个size和缓冲区的大小无关,只是数据包的数量。
现在假设TCP_WND是1024,网络端快速发过来几十个1字节的数据包,这时候上面的mbox就会很快溢出,溢出的第一个包在pcb->refused_data里面会缓存一下,不过这个能力也很有限,等pcb->refused_data也存不下了这个pbuf就被直接丢弃了。这是在TCP_WND还没用完的情况下就丢包了。
更严重一点的情况,如果上面这种状况发生的同时lwip还在向上位机程序发数据的话,之前被丢弃的包很可能同时也是这些数据包的ACK,ACK丢了就会导致lwip向上位机重发这些数据,而上位机这边也在不停的重发(window没用完却丢包了必然会重发),然后两边就互不理睬各发各的。。。最后rst。断开。

这种情况有两个前提,一个是接受速度没那么快,这种情况我觉得还是比较容易发生的,比如一边收网络包一边发送到usart,波特率慢的时候网络接收就会很慢。
还有一个前提是上位机发来大量段数据包,且这些数据包总和x10 < TCP_WND。

目前还没想到很好的办法解决这个问题,加大mbox或者减小window只能稍微缓解一下,只要mbox的size    
帖子: 33
注册: 2009年 12月 20日 03:35 页首
--------------------------------------------------------------------------------
Re: 搞死LWIP的方法
由 bernard » 2010年 4月 18日 07:23  

嗯,这个确实是个大问题。

修正下才是,mbox机制需要修改下,改成非mbox机制比较好。
我的邮件地址:
和RT-Thread相关的基础技术问题请在论坛上直接发帖,就不要发信给我啦,谢谢。bernard  
   
帖子: 1362
注册: 2008年 5月 10日 07:22 页首
--------------------------------------------------------------------------------
Re: 搞死LWIP的方法
由 mbbill » 2010年 4月 18日 14:51  

这样工作量有点大了   

另外这个问题在优化lwip的时候也很可能发生,比如为了提高性能把TCP_BUF和TCP_WND定的比较大,这时候很可能就会发生这种现象,wireshark一抓全都是重发的包。mbbill  
   
帖子: 33
注册: 2009年 12月 20日 03:35 页首
--------------------------------------------------------------------------------
Re: 搞死LWIP的方法
由 bernard » 2010年 4月 18日 16:14  

工作量可能还行,可以考虑把mbox更改成数据队列的方式。只是这样的话,那么lwip那边tcp线程确实会修改一些了。这个加上,系能是否会好些呢。

找个时间验证一把。
 
 
 

回复

105

帖子

0

TA的资源

一粒金砂(中级)

14
 

“lwip的netconn有一个缺陷” 也许是的!我没研究过!

但是raw接口的函数应该没什么问题吧

 
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

15
 
原帖由 历史的天空 于 2011-3-16 23:38 发表 “lwip的netconn有一个缺陷” 也许是的!我没研究过!但是raw接口的函数应该没什么问题吧
netconn其实是基于raw_api的。
 
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

16
 
LZ,有结果了么?
 
 
 

回复

144

帖子

0

TA的资源

一粒金砂(中级)

17
 
原帖由 ebuffalo 于 2011-3-15 19:10 发表
https://bbs.eeworld.com.cn/viewthread.php?tid=156925&page=1#pid819892

有新进展了么?LS在上面的帖子中不是说自己写了个协议栈了事。

??????????????????
 
 
 

回复

422

帖子

0

TA的资源

纯净的硅(高级)

18
 

回复 楼主 qwertyer2010 的帖子

tcp_bind这个也不用了吗?
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表