Forum: Mikrocontroller und Digitale Elektronik lwIP Microcontroller reagiert nicht auf TCP `SYN`


von etechniker (Gast)


Lesenswert?

Hallo zusammen

Ich sende Daten von einem Linux PC an einen TMS320F2838D auf dem lwIP 
läuft. Ich möchte erreichen, dass man den entsprechenden Linux Prozess 
beenden kann und die TCP Verbindung danach schnell wiederaufbauen kann 
durch einen Neustart des Linux Prozesses.

Wenn ich das nun auf meinem Rechner teste funktioniert das jeweils fünf 
mal gut, d.h. ich kann den Linux Prozess mittels SIGINT beenden und die 
TCP Verbindung wird korrekt geschlossen, auf Wireshark sehe ich das 
entsprechende FIN-ACK-FIN-ACK Muster.

Komischerweise funktioniert es nach dem fünften Wiederaufbauversuch 
nicht mehr, d.h. wenn ich den Prozess zum fünften mal Neustarte sehe ich 
auf Wireshark ein `SYN` Paket an den uC aber der lwIP uC reagiert nicht 
darauf.

Ich sehe kein Antwortpaket des uC und wenn ich den uC debugge wird die 
entsprechende callback Routine `accept_cb` zum Akzeptieren von TCP 
Verbindungen auch nicht aufgerufen.

Auf dem uC scheint jedoch immer noch ein "welcoming_socket" vorhanden zu 
sein der sich im state `LISTEN` befindet (also derselbe welcoming_socket 
der zuvor bereits vier mal eine TCP Verbindung ohne Probleme 
entgegengenommen hat), das zeigt zumindest der Debugger an wenn ich mir 
die entsprechende struct anschaue.

Ich benutze den folgenden Code zum Aufsetzen des welcoming_socket:
1
void setupCommInterface(void){
2
    //create a new tcp pcb
3
    struct tcp_pcb* connection_pcb = tcp_new();
4
    //bind the pcb to the port comm_port
5
    err_t err=tcp_bind(connection_pcb,IP_ANY_TYPE,COMM_PORT);
6
    if(err!=ERR_OK){
7
        if(err==ERR_USE){
8
            while(1){}
9
        }
10
        else if(err==ERR_VAL){
11
            while(1){}
12
        }
13
        while(1){}
14
    }
15
16
    welcoming_socket_pcb=tcp_listen(connection_pcb);
17
18
    tcp_accept(welcoming_socket_pcb,accept_cb);
19
}

Die callback Routine welche die eingehende TCP Verbindung akzeptieren 
sollte ist die folgende:
1
// TCP accept callback function is called when an incoming TCP connection on COMM_PORT is established
2
err_t accept_cb(void * arg, struct tcp_pcb* new_pcb, err_t err){
3
    if(err==ERR_OK){
4
        //set the connection active flag
5
        connection_active=true;
6
        //register callback for received data
7
        tcp_recv(new_pcb, tcp_recvd_cb);
8
        return ERR_OK;
9
    }
10
    else{
11
        while(1){
12
            //wait forever to preserve debug state
13
        }
14
    }
15
}

Gibt es da vielleicht irgendeine Socket-Option die den fünften 
verbindungsaufbau unterbindet?

von Stefan F. (Gast)


Lesenswert?

Nur so eine Vermutung ins Blaue:

Der Mikrocontroller kann bis zu 5 Verbindungen gleichzeitig annehmen. 
Nachdem eine Verbindung geschlossen wurde, bleibt irgend eine Resource 
fälschlicherweise weiterhin belegt.

Dein Problem ist beginnt also vermutlich schon bei der ersten 
Verbindung.

Ich habe mir beim Vorgänger (µIP) eine Schnittstelle zum Monitoring 
eingebaut, wo ich unter anderem den Status der 5 Kanäle sehen konnte. 
Vielleicht würde dir so eine Ausgabe auch helfen.

von Programmierer (Gast)


Lesenswert?

Weiß gerade nicht wie das bei lwIP funktioniert, reagierst du auf der 
uC-Software auf das Schließen der Verbindung, d.h. schließt du den PCB 
(new_pcb) ? Wenn nicht, hängt der eventuell noch rum und blockiert 
Ressourcen. Man kann in der lwIP-Config einstellen wie viele 
PCBs/Sockets gleichzeitig möglich sind...

von etechniker (Gast)


Lesenswert?

Programmierer schrieb:
> Weiß gerade nicht wie das bei lwIP funktioniert, reagierst du auf
> der
> uC-Software auf das Schließen der Verbindung, d.h. schließt du den PCB
> (new_pcb) ? Wenn nicht, hängt der eventuell noch rum und blockiert
> Ressourcen. Man kann in der lwIP-Config einstellen wie viele
> PCBs/Sockets gleichzeitig möglich sind...

Vielen Dank für die Antwort. Das Schliessen funktioniert wie im unteren 
Code gezeigt. Wenn der lwIP ein `FIN` erhält ruft er die callback 
Funktion `tcp_recvd_cb` auf mit einem `NULL` buffer `p`. Daraufhin führe 
ich `tcp_close()` aus.

Manchmal kriege ich den Fehler scheinbar schon nach vier Versuchen. Aber 
es scheint tatsächlich so als ob `tcp_close()` nicht ganz alle 
Ressourcen sofort freigibt.

1
// TCP received callback function is called when new data was received on COMM_PORT
2
err_t tcp_recvd_cb(void* arg, struct tcp_pcb* tcppcb, struct pbuf* p,err_t err){
3
    //payload being NULL indicated that the TCP connection has been terminated
4
    if(p==NULL){
5
        connection_active=false;
6
        // close the pcb
7
        tcp_close(tcppcb);
8
        // listen to new connections again
9
        //tcp_accept(welcoming_socket_pcb,accept_cb);
10
        return ERR_OK;
11
    }
12
    else{
13
        if(err==ERR_OK){
14
            // -- process the data in p , p is NULL if the remote host terminated the connection --
15
            memcpy(buffer,p->payload,p->len);
16
            u16_t bytes_read=p->len;
17
            //indicate that a new command is available for processing in the buffer
18
            command_available=true;
19
            // -- indicate that bytes were read and we are ready to receive more data --
20
            tcp_recved(tcppcb,bytes_read);   //indicate that no_bytes_read were read and we are ready to receive more data
21
            // -- echo the received data back
22
            //tcp_write(tcppcb,buffer,bytes_read,TCP_WRITE_FLAG_COPY);
23
            return ERR_OK;
24
        }
25
        else{
26
            //wait forever and preserve debug state
27
            while(1);
28
        }
29
    }
30
}

von 542325 (Gast)


Lesenswert?

das ist witzigerweise "normal"

die alten Verbindungen stehen im "FIN_WAIT_2"
das hat mir auch schon oft den spass verdorben

ich habe bei mir die socket API ..daher ist das etwas anders.

Ich setze aber vor dem close alle sockets in den nonblocking mode
und immer mit den Flags :  SO_REUSE

sonst vlt vor dem close: lwip_shutdown(stream->sock, SHUT_RDWR);

holzhammermethode: SO_LINGER vor dem close

das killt den TIME_WAIT status

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.