2016-12-07 17 views
1

接続でTCPリセットを強制しようとしています。 SO_LINGERを0に設定し、close()を呼び出すことをお勧めします。SO_LINGERのclose()はRSTを送信しません

私はまさにこれをやっていますが、接続はESTABLISHED状態のままです。 ソケットが非ブロッキングモードで動作しています。オペレーティングシステムはRaspbianです。

コード:

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のトレースは同様に全くRSTを示しません。

アプリケーションの他のスレッドは、そのソケットで操作を実行していません。

何が間違っているのかわからないので、どんな提案も大歓迎です。


問題がsystem()呼び出して作成した子に漏れるファイルディスクリプタとあった

を解決しました。 実際、lsof -i tcpですべてのTCPソケット記述子を列挙したとき、親プロセスからファイル記述子を開いたことがわかりました。

解決策は、フォークされたプロセスでファイルディスクリプタを閉じることを要求していました(accept()の直後)。

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

プロセスをフォークしましたか? 'close()'は、フォークがあった場合には* last * closeであるときの動作のみを行います。 – EJP

答えて

1

あなたのケースでは、closeを呼び出した後、データを送受信できなくなりました。また、closeの呼び出し後、RSTはソケット記述子の参照カウンタが0になったときにのみ送信されます。その後、接続はCLOSEDの状態になり、受信のデータと送信バッファは破棄されます。
答えは、あなたがプロセスをどのようにフォークしたかにあります(EJPのコメントのように)。 forkを呼び出した後、親プロセスの受け入れたソケットを閉じなかったようです。したがって、ソケット参照カウンタはゼロではなく、closeの直後にRSTはありません。
このような状況は、UNIXネットワークプログラミングのStevensによってよく説明されています。

+0

私を正しい方向に向けてくれてありがとう。問題は即座ではありませんでした。ファイルディスクリプタはsystem()への呼び出しによってリークされました(実際にはforkを実行します)。正しいファイル記述子オプションを設定すると、問題が解決しました。 –

関連する問題