[求助] tcp通信遇到的问题

qwertyer2010   2011-3-28 14:34 楼主
不好意思,小弟刚接触LWIP,在做TCP收发通信的时候遇到,电脑是客户端,目标板是服务端,电脑发送一个TCP数据包,目标板解析,如果符合约定,则回复相应格式的帧,但是发现电脑接到数据所要等待的时间比较长,大约有2S的样子。后来用TCP抓包工具看到下面那样,会出现红色的重发数据。由于是新手,不知道怎么解决它,有高手帮忙分析下这个是什么原因造成的?小弟万分感谢 2.JPG

回复评论 (7)

希望高手帮帮忙~~~~
以下是我接受—解析—发送部分源码
static err_t TCP_SER_Receive(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{

   tTCPSessionData *pState;
   pState=&g_sTCPSession;
   unsigned char ProtID[2]={0x00,0x00};
   unsigned short regLen;
   unsigned short regLen_tmp;         // ether_cmd register calculate tmp.
   unsigned char  eth_send_data[256];  //ethernet send byte ptr.
   unsigned short uslen;              //send byte length.
   unsigned short usaddr,byte_addr=0;  //inqire byte frist address.
   unsigned char byte_len,ucCunt;

    if((err == ERR_OK) && (p != NULL))                                 
   {      
/* Inform TCP that we have taken the data. */
           tcp_recved(pcb,p->tot_len);
          
           eth_cmd= (unsigned char*)p->payload;
           if((*(eth_cmd+2)==ProtID[0])&&(*(eth_cmd+3)==ProtID[1]))
           {
          if((*(eth_cmd+6)==s_psComData->ucMeterAddr)&&((*(eth_cmd+7)==0x03)||(*(eth_cmd+7)==0x04)))
                  {
         regLen=((unsigned short)s_psComData->ucREGnumH)|s_psComData->ucREGnumL;    //计算表里面的寄存器数目
         usaddr = (unsigned short)*(eth_cmd+8)|(*(eth_cmd+9));
                 uslen = (unsigned short)*(eth_cmd+10)|(*(eth_cmd+11));
                 regLen_tmp = usaddr+uslen; // 计算命令帧中的寄存器数
         
                 //判断寄存器是不是越界,因为表内寄存器有限
                 if((regLen_tmp<=regLen)&&((*(eth_cmd+10)==0x00)&&(*(eth_cmd+11)<0x80)))
                 {
           byte_addr = usaddr*2;
                   byte_len = (*(eth_cmd+11))*2;
                   eth_send_data[0] = *eth_cmd;
                   eth_send_data[1] = *(eth_cmd+1);
                   eth_send_data[2] = ProtID[0];
                   eth_send_data[3] = ProtID[1];
                   eth_send_data[4] = (unsigned char)(((byte_len+3)>>8)&0xFF);
                   eth_send_data[5] = (unsigned char)((byte_len+3)&0xFF);
                   eth_send_data[6] = s_psComData->ucMeterAddr;
                   eth_send_data[7] = *(eth_cmd+7);
                   eth_send_data[8] = byte_len;
                   for(ucCunt=0;ucCunt                    eth_send_data[9+ucCunt]=g_psMBdataReps->ucData[byte_addr+ucCunt];

                   lCount=byte_len+9;
                   if(tcp_sndbuf(tpcb) < lCount)
                         {
                           lCount = tcp_sndbuf(tpcb);
                                }
                  
           // Write the local buffer into the TCP buffer
                   tcp_write(tpcb,eth_send_data,(byte_len+9),0);
           pbuf_free(p);                            // 释放缓冲区数据
      
        }
点赞  2011-3-29 09:56

回复 楼主 qwertyer2010 的帖子

请问楼主,你说的重发是电脑给目标板发,还是目标板向电脑重发?
点赞  2011-3-29 13:43
目标板对主机重发
点赞  2011-3-29 13:53
加tcp_output(pcb);试试
点赞  2011-3-29 14:11
加过了,没用,但是发现如果字节少就不会重发!
苦恼中~~
点赞  2011-3-29 15:10
楼主,接收部分的代码呢,我觉得是在接收部分代码有问题
点赞  2011-4-18 10:57

解决了吗?我给个你参考

#include
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_nvic.h"
#include "inc/hw_types.h"
#include "inc/hw_sysctl.h"

#include "driverlib/ethernet.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/systick.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"

#include "drivers/rit128x96x4.h"

#include "utils/lwiplib.h"
#include "utils/ustdlib.h"

#include "lwip/tcp.h"


#define My_Mac_ID         {0X00,0x14,0x97,0x0F,0x1D,0xE3}  //存储以太网控制器的物理地址,即MAC地址

#define MY_IP_ID               {192,168,14,210}                   //以太网通信的IP地址
#define IP_MARK_ID           {255,255,255,0}                           //255.255.255.0,子网掩码
#define MY_GATEWAY_ID   {192,168,14,254}                     //以太网通信的网关地址
static const unsigned char pucMACAddress[]=My_Mac_ID;
static const unsigned char IPAddress[] = MY_IP_ID;
static const unsigned char NetMaskAddr[] = IP_MARK_ID;
static const unsigned char GwWayAddr[] = MY_GATEWAY_ID;
#define SYSTICKHZ                100
#define SYSTICKMS               (1000 / SYSTICKHZ)
#define SYSTICKUS               (1000000 / SYSTICKHZ)
#define SYSTICKNS               (1000000000 / SYSTICKHZ)

static struct tcp_pcb *g_psPCB = NULL;

typedef struct
{
    unsigned long ulRetryCount;               
    tBoolean bCONTROLSent;               
}
tAPPState;

struct pbuf *fp=NULL;
tAPPState *fpState=NULL;       

void
SysTickIntHandler(void)
{
   
         lwIPTimer(SYSTICKMS);

}

void
UARTSend(const unsigned char *pucBuffer, unsigned long ulCount)
{
    //
    // Loop while there are more characters to send.
    //
    while(ulCount--)
    {
        //
        // Write the next character to the UART.
        //
        UARTCharPutNonBlocking(UART0_BASE, *pucBuffer++);
    }
}
//当数据被正确发送到远程主机后(收到ACK),该函数会被调用。
static err_t
App_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
   LWIP_UNUSED_ARG(len);

  if(!arg) {
    return ERR_OK;
  }
    tcp_arg(pcb, NULL);
    tcp_sent(pcb, NULL);
    tcp_recv(pcb, NULL);
    mem_free(arg);
    tcp_close(pcb);

   
    return ERR_OK;

}

static err_t
APP_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
        tAPPState *pState;
        char *q;
        unsigned int i;
        q=(char*) malloc(p->len);
        for(i=0;i<=p->len;i++)
                *(q+i)=*((char*)p->payload+i);
        pState = arg;
        fp=p;
        if((err == ERR_OK) && (p != NULL))
        {
                tcp_recved(pcb, p->tot_len);
                 
                if(strncmp(p->payload, "LED ON", 6) == 0)
                {
                         GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_PIN_0);
                         pbuf_free(p);
                         tcp_sent(pcb, App_sent);
                }
                if(strncmp(p->payload, "LED OFF", 7) == 0)
                {
                         GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0);
                         pbuf_free(p);
                         tcp_sent(pcb, App_sent);
                }
       
        //处理接收部分。
        UARTSend((unsigned char *)p->payload,p->len);
        RIT128x96x4Enable(1000000);
        RIT128x96x4StringDraw("                          ",0,16,15);
        RIT128x96x4StringDraw(q,0,16, 15);
        RIT128x96x4Disable();
        //发送数据
        //send_data();
        free(q);
       
        }

         if((err == ERR_OK) && (p == NULL))
    {
        //
        // Close the connection.
        //
        tcp_arg(pcb, NULL);
        tcp_sent(pcb, NULL);
        tcp_recv(pcb, NULL);
        mem_free(pState);
        tcp_close(pcb);
    }



    return ERR_OK;  
}

//static void
//APP_error(void *arg, err_t err)
//{
//   //处理错误
//    if(arg != NULL)
//    {
//        mem_free(arg);
//    }
//}

//static err_t
//APP_poll(void *arg, struct tcp_pcb *pcb)
//{
//    tAPPState *pState;
//
//   
//    pState = arg;
//
//  
//    pState->ulRetryCount++;
//
//   
//    if(pState->ulRetryCount++ >= 120)
//    {        //约120s之后无数据发送就会断开就断开连接。
//        tcp_abort(pcb);
//        return(ERR_ABRT);
//    }
//
//  
//    return ERR_OK;
//}


static err_t
APP_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
tAPPState *pState;
tcp_setprio(pcb, TCP_PRIO_MIN);
pState = mem_malloc(sizeof(tAPPState));
fpState=pState;
if(pState == NULL)
    {
        return(ERR_MEM);
    }
    pState->ulRetryCount = 0;
    pState->bCONTROLSent = false;

        tcp_arg(pcb, pState);

        tcp_recv(pcb, APP_recv);

//        tcp_err(pcb, APP_error);
        //这里设置2每500ms就调用一次。4就是1s
        //注意其中的APP_poll只有当协议栈中没有数据进出时,才会被调用。
        //我们可以用它来发送某些数据。
        //
//        tcp_poll(pcb, APP_poll, 4);
        RIT128x96x4Enable(1000000);
        RIT128x96x4StringDraw("connect succeed        ",0,8, 15);
        RIT128x96x4Disable();
         
        tcp_write(pcb,"hello!\n",6,TCP_WRITE_FLAG_COPY);
        tcp_output(pcb);
       
        return(ERR_OK);

}

void
io_init(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_0);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0,1);
}

//*****************************************************************************
//
// Send a string to the UART.
//
//*****************************************************************************

int
main(void)
{
       
   struct ip_addr ulIPAddr,ulNetMask,ulGWAddr;
   struct tcp_pcb *Pcb1;

//   struct pbuf *p;

      if(REVISION_IS_A2)
    {
        SysCtlLDOSet(SYSCTL_LDO_2_75V);
    }

    SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
                   SYSCTL_XTAL_8MHZ);
          
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);
    SysCtlPeripheralReset(SYSCTL_PERIPH_ETH);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3);

        io_init();       

    SysTickPeriodSet(SysCtlClockGet() / SYSTICKHZ);
    SysTickEnable();
    SysTickIntEnable();

        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable processor interrupts.
    //
    IntMasterEnable();

    //
    // Set GPIO A0 and A1 as UART pins.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    //
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
                        (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                         UART_CONFIG_PAR_NONE));

    //
    // Enable the UART interrupt.
    //
    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

    //


       
        IP4_ADDR(&ulIPAddr,IPAddress[3],IPAddress[2],IPAddress[1],IPAddress[0]);
    IP4_ADDR(&ulNetMask,NetMaskAddr[3],NetMaskAddr[2],NetMaskAddr[1],NetMaskAddr[0]);
    IP4_ADDR(&ulGWAddr,GwWayAddr[3],GwWayAddr[2],GwWayAddr[1],GwWayAddr[0]);
    lwIPInit(pucMACAddress,ulIPAddr.addr, ulNetMask.addr, ulGWAddr.addr, IPADDR_USE_STATIC);


    g_psPCB=Pcb1 = tcp_new();

    tcp_bind(Pcb1, IP_ADDR_ANY,1027);  //1027
    Pcb1 = tcp_listen(Pcb1);
    tcp_accept(Pcb1, APP_accept);  //
        //tcp_send(Pcb1, send_data);

        RIT128x96x4Init(1000000);
    RIT128x96x4StringDraw("host,wellcome", 0, 0, 15);
        RIT128x96x4StringDraw("waiting for connect", 0, 8, 15);
        RIT128x96x4Disable();       
        while(1)
        {
        }


}
点赞  2011-4-18 22:30
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复