2012-12-03 59 views
2

亲爱的同学StackOverflowers,Microchip的TCP/IP堆栈PIC18F无效包SEQ/ACK号

林工作的一个项目,以实现对我的自定义(和测试)董事会通过关于PIC18F87J60东西使用的是Microchip TCP/IP协议栈。作为测试,我编写了一些代码来建立连接,将其保持x秒,然后优雅地关闭它。我已经将它作为一个有限状态机来实现。我没有添加发送和接收数据。

但是,我的程序无法建立连接。使用Wireshark我注意到我的设备通过DHCP成功接收IP地址,并且ARP解析正确完成。现在我遗漏了DNS,因为这也出错了,但我会在稍后解决。 我还看到第一个SYN数据包是由我的设备发送的,并且应该是服务器应答的,但3次握手中的3e步骤出错了。确认号码只是一个随机数,所以服务器会感到困惑,并用RST数据包重置连接。 然后我的设备使用另一个随机序列号的ACK数据包确认重置,服务器以某种方式接受此数据包。然后服务器尝试再次使用SYN数据包设置连接,但是我的代码不监听传入连接,因此连接结束。

这里是我的代码:

#define THIS_IS_STACK_APPLICATION 
#include "TCPIP.h" 

APP_CONFIG AppConfig; 

ROM char serverAddress[] = "data.zienu.eu"; //unused in this codefile: DNS doesn't work yet 
ROM char serverIP[] = "80.69.92.56"; 
short authenticationPort = 5588; 

typedef enum _SOCKET_STATE { 
    SOCKET_DONE = 0, 
    SETUP_CONNECTION, 
    CONNECTING, 
    CONNECTED, 
    AWAITING_ANSWER, 
    SENDING_DATA, 
    CLOSE_CONNECTION, 
    DISCONNECTING, 
    DISCONNECTED 
} SOCKET_STATE; 

typedef struct _CONNECTION { 
    TCP_SOCKET socketID; 
    SOCKET_INFO* remoteInfo; 
    const char* remoteHostName; 
    WORD remotePort; 
    SOCKET_STATE state, previousState; 
    DWORD timeOut; 
    BYTE purpose; 
} CONNECTION; 

void InitHardware(); 
void AuthenticateTask(); 
void FTPDownloadTask(); 
void HandleTCPConnection(CONNECTION* connection); 

ROM BYTE SerializedMACAddress[6] = {MY_DEFAULT_MAC_BYTE1, MY_DEFAULT_MAC_BYTE2, MY_DEFAULT_MAC_BYTE3, MY_DEFAULT_MAC_BYTE4, MY_DEFAULT_MAC_BYTE5, MY_DEFAULT_MAC_BYTE6}; 
void InitAppConfig(void) { 
    AppConfig.Flags.bIsDHCPEnabled = TRUE; 
    AppConfig.Flags.bInConfigMode = TRUE; 
    memcpypgm2ram((void*)&AppConfig.MyMACAddr, (ROM void*)SerializedMACAddress, sizeof(AppConfig.MyMACAddr)); 
    AppConfig.MyIPAddr.Val = MY_DEFAULT_IP_ADDR_BYTE1 | MY_DEFAULT_IP_ADDR_BYTE2<<8ul | MY_DEFAULT_IP_ADDR_BYTE3<<16ul | MY_DEFAULT_IP_ADDR_BYTE4<<24ul; 
    AppConfig.DefaultIPAddr.Val = AppConfig.MyIPAddr.Val; 
    AppConfig.MyMask.Val = MY_DEFAULT_MASK_BYTE1 | MY_DEFAULT_MASK_BYTE2<<8ul | MY_DEFAULT_MASK_BYTE3<<16ul | MY_DEFAULT_MASK_BYTE4<<24ul; 
    AppConfig.DefaultMask.Val = AppConfig.MyMask.Val; 
    AppConfig.MyGateway.Val = MY_DEFAULT_GATE_BYTE1 | MY_DEFAULT_GATE_BYTE2<<8ul | MY_DEFAULT_GATE_BYTE3<<16ul | MY_DEFAULT_GATE_BYTE4<<24ul; 
    AppConfig.PrimaryDNSServer.Val = MY_DEFAULT_PRIMARY_DNS_BYTE1 | MY_DEFAULT_PRIMARY_DNS_BYTE2<<8ul | MY_DEFAULT_PRIMARY_DNS_BYTE3<<16ul | MY_DEFAULT_PRIMARY_DNS_BYTE4<<24ul; 
    AppConfig.SecondaryDNSServer.Val = MY_DEFAULT_SECONDARY_DNS_BYTE1 | MY_DEFAULT_SECONDARY_DNS_BYTE2<<8ul | MY_DEFAULT_SECONDARY_DNS_BYTE3<<16ul | MY_DEFAULT_SECONDARY_DNS_BYTE4<<24ul; 

    // Load the default NetBIOS Host Name 
    memcpypgm2ram(AppConfig.NetBIOSName, (ROM void*)MY_DEFAULT_HOST_NAME, 10); 
    FormatNetBIOSName(AppConfig.NetBIOSName); 
} 

void InitHardware() { 
    /** \var isBoot (LATH0_bit) tells the boot-interrupt handler that boot is busy */ 
    LATHbits.LATH0 = 1; 

    ADCON1 |= 0x0f;   // adc pins as I/0 
    CMCON |= 7;   // Disable comperator 

    OSCCON = 0x04; 
    OSCTUNE = 0x40; //41 MHz 

    /******************************************************************/ 
    // init======== 
// Het TRISA en TRISF register moeten goed zijn ingesteld voor de analoge input: 
    PORTA = 0x00; 
    TRISA = 0x20; /* Bit 1 and 2 are used by ethernet LEDS */ 
    PORTB = 0x00; 
    TRISB = 0x00; /* output mode */ 
    PORTC = 0x03; /* LED R en G off */ 
    TRISC = 0xc0; /* Bit 6 and 7 are used by UART 1 */ 
    PORTD = 0x00; /* used to display ethernetsecond_timer in DEBUG mode*/ 
    TRISD = 0x00; /* output mode */ 
    PORTE = 0x00; 
    TRISE = 0x00; /* output mode */ 
    PORTF = 0x00; 
    TRISF = 0x0E; /* output mode */ 
    PORTG = 0x00; 
    TRISG = 0x00; 
    PORTH = 0x00; 
    TRISH = 0x00; 

    /* interrupt priorities are possible with microC */ 
    IPR1bits.ADIP = 0;  //give ADC LOW interrupt priority 
    RCONbits.IPEN = 1;  //Enable interrupt priorities 
    INTCON2bits.RBPU = 1; // Disable internal PORTB pull-ups 

    INTCONbits.GIEH = 1; 
    INTCONbits.GIEL = 1; 
} 

void interrupt low_priority LowISR(void) { 
    TickUpdate(); 
} 

void interrupt HighISR(void) { 
} 

void HandleTCPConnection(CONNECTION* connection) { 
    switch(connection->state) { 
     case SETUP_CONNECTION: 
      if(!AppConfig.Flags.bInConfigMode) { 
       connection->socketID = TCPOpen((DWORD) (PTR_BASE)&serverIP[0], TCP_OPEN_ROM_HOST, connection->remotePort, connection->purpose); 

       connection->timeOut = TickGet() + TICK_SECOND * 15; 
       connection->previousState = SETUP_CONNECTION; 
       connection->state = CONNECTING; 
       TCPWasReset(connection->socketID); 
      } 
      break; 
     case CONNECTING: 
      if(TCPIsConnected(connection->socketID)) { 
       connection->previousState = CONNECTING; 
       connection->state = CONNECTED; 
       connection->remoteInfo = TCPGetRemoteInfo(connection->socketID); 
       connection->timeOut = TickGet() + TICK_SECOND * 10; 
      } 
      else if(TickGet() >= connection->timeOut) { 
       connection->previousState = CONNECTING; 
       connection->state = CLOSE_CONNECTION; 
      } 
      break; 
     case CONNECTED: 
      if(TickGet() >= connection->timeOut) { 
       connection->previousState = CONNECTED; 
       connection->state = CLOSE_CONNECTION; 
      } 
      else if(TCPWasReset(connection->socketID)) { 
       connection->previousState = CONNECTED; 
       connection->state = CLOSE_CONNECTION; 
      } 
      break; 
     case CLOSE_CONNECTION: 
       connection->previousState = CLOSE_CONNECTION; 
       connection->state = DISCONNECTING; 
       TCPDisconnect(connection->socketID);  //Send a TCP FIN packet 
       connection->timeOut = TickGet() + TICK_SECOND * 5; 
      break; 
     case DISCONNECTING: 
      if(TCPIsConnected(connection->socketID)) { 
       connection->previousState = DISCONNECTING; 
       connection->state = DISCONNECTED; 
      } 
      else if(TickGet() >= connection->timeOut) { 
       TCPDisconnect(connection->socketID); 
       TCPDisconnect(connection->socketID); //Time out: Send a RST packet and proceed 
       connection->previousState = DISCONNECTING; 
       connection->state = DISCONNECTED; 
      } 
      break; 
     case DISCONNECTED: 
      connection->previousState = DISCONNECTED; 
      connection->state = SOCKET_DONE; 
      break; 
     case SOCKET_DONE: 
      break; 
     default: 
      break; 
    } 
} 

void main() { 
    InitHardware(); 
    TickInit(); 
    InitAppConfig(); 
    StackInit(); 

    CONNECTION connection; 
    connection.purpose = TCP_PURPOSE_CUSTOM_FTP_CMD; 
    connection.remoteHostName = serverIP; 
    connection.remotePort = authenticationPort; 
    connection.previousState = SOCKET_DONE; 
    connection.state = SETUP_CONNECTION; 
    while(TRUE) { 
     HandleTCPConnection(&connection); 
     StackTask(); 
     StackApplications(); 
    } 
} 

这里是Wireshark logs的截图。

由于提前, BitJunky

编辑: 这里是wireshark dumpfile。我在MAC地址上过滤,因此DHCP转储的一部分未显示在此转储中。

+0

你可以用完整的SEQ/ACK nunmbers发布跟踪吗?也许像一个tcpdump? – cxxl

+0

@cxxl在原文中看到我的编辑 – Jupiter

回答

1

我解决了这个问题。我认为TCPIP堆栈与高科技编译器兼容,但似乎并非如此。 C18和XC8编译器与我发布的代码完美配合。

Greetz BitJunky