不好意思,小弟刚接触LWIP,在做TCP收发通信的时候遇到,电脑是客户端,目标板是服务端,电脑发送一个TCP数据包,目标板解析,如果符合约定,则回复相应格式的帧,但是发现电脑接到数据所要等待的时间比较长,大约有2S的样子。后来用TCP抓包工具看到下面那样,会出现红色的重发数据。由于是新手,不知道怎么解决它,有高手帮忙分析下这个是什么原因造成的?小弟万分感谢
希望高手帮帮忙~~~~
以下是我接受—解析—发送部分源码
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); // 释放缓冲区数据
}
回复 楼主 qwertyer2010 的帖子
请问楼主,你说的重发是电脑给目标板发,还是目标板向电脑重发?
解决了吗?我给个你参考
#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)
{
}
}