2016-12-07 2 views
1

Ich versuche TCP-Reset auf einer Verbindung zu erzwingen. Die vorgeschlagene Möglichkeit besteht darin, SO_LINGER auf 0 und den Aufruf close() zu setzen.Schließen() mit SO_LINGER wird nicht senden RST

Ich mache genau das, aber die Verbindung bleibt im Zustand ESTABLISHED. Die Buchse arbeitet im nicht blockierenden Modus. Das Betriebssystem ist Raspbian.

Der Code:

struct linger l; 
l.l_onoff = 1; 
l.l_linger = 0; 

if (setsockopt(server->connection_socket, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) != 0) { 
    LOG_E(tcp, "setting SO_LINGER failed"); 
} 

if (close(server->connection_socket) != 0) { 
    LOG_E(tcp, "closing socket failed"); 
} 

server->connection_socket = 0; 
LOG_I(tcp, "current TCP connection was closed"); 

Wireshark Spur zeigt auch keine RST.

Keine anderen Threads der Anwendung führen einen Vorgang an diesem Socket durch.

Ich kann nicht herausfinden, was falsch ist, würde jeder Vorschlag sehr geschätzt werden.


GELöST

Das Problem war mit Dateideskriptoren Kindern undichten durch system() Anruf erstellt. In der Tat, als ich alle TCP-Socket-Deskriptoren mit lsof -i tcp aufgelistet, fand ich heraus, dass untergeordnete Prozesse Dateideskriptor aus dem übergeordneten Prozess geöffnet hatte (obwohl Eltern bereits nicht).

Die Lösung forderte, dass der Dateideskriptor in einem gegabelten Prozess geschlossen wird (direkt nach accept()).

fcntl(server->connection_socket, F_SETFD, FD_CLOEXEC) 
+1

Haben Sie einen Prozess gegabelt? 'close()' wird nur tun, was es tut, wenn es das * letzte * Ende ist, wenn es Gabeln gab. – EJP

Antwort

1

In Ihrem Fall können Sie nicht mehr Daten senden und empfangen, nachdem close aufrufen. Auch nach close Aufruf der RST wird nur gesendet werden, wenn der Referenzzähler des Socket-Deskriptor wird 0. Dann geht die Verbindung in CLOSED Zustand und Daten im Empfang und die Sendepuffer werden verworfen.
Wahrscheinlich liegt die Antwort darin, wie Sie einen Prozess gegabelt haben (wie von EJP im Kommentar erwähnt). Offenbar haben Sie den akzeptierten Socket im übergeordneten Prozess nach dem Aufruf von fork nicht geschlossen. Also ist der Socket-Referenzzähler ungleich Null und es gibt keine RST unmittelbar nach Ihrem close.
Solche Situationen werden von Stevens in UNIX Network Programming gut beschrieben.

+0

Danke, dass Sie mich in die richtige Richtung weisen. Das Problem war nicht sofort - Dateideskriptoren wurden durch Aufruf von system() durchgesickert (was tatsächlich eine Verzweigung darstellt). Durch Festlegen der richtigen Dateideskriptoroption wurde das Problem behoben. –

Verwandte Themen