親愛なる仲間のStackOverflowers、
Microchip社のTCP/IPスタックを使用して、カスタム(およびテスト済み)ボードのPIC18F87J60に何かを実装するプロジェクトに取り組んでいます。テストとして、接続をセットアップし、それを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ログのスクリーンショットです。
よろしくお願いします、BitJunky
編集:これがwiresharkのdumpfileです。MACアドレスでフィルタリングしたため、DHCPプロセスの一部がこのダンプに表示されません。