2016-07-21 3 views
1

Как сбросить сокет accept ed на уровне приложения либо с помощью IO :: Socket :: INET в perl, либо в C?Сброс подключения сокета TCP из приложения

Существует программка bind ИНГ, listen ИНГ на TCP порт и accept S соединение с клиентом, после чего он read s и write сек некоторые данные. Если я просто close или shutdown сокет, уровень TCP изящно завершается (с пакетом FIN), а не я бы генерировал RST-пакет.

+0

AFAIK, нет никакого способа сделать это, используя сокет, который вы отправляли и получали. Вы всегда можете вручную создать свой собственный пакет RST и отправить его своему сверстнику, но вам нужно создать отдельный сырой пакетный сокет для его отправки. Linux также имеет функцию SOCK_DESTROY (условно включенную в ядро), которая может использоваться соответствующим образом привилегированным процессом для закрытия произвольного соединения, но также полностью вне диапазона вашего приложения. Почему вы все равно хотите завершить работу с RST? –

+2

Вы можете попробовать опцию сокета SO_LINGER с нулевым таймаутом, [согласно некоторым ресурсам] (http://stackoverflow.com/questions/3757289/tcp-option-so-linger-zero-when-its-required), он будет генерировать RST пакет вместо FIN. –

+0

@SlavaBacherikov спасибо, он работает в коде: '$ socket = IO :: Socket :: INET-> new (Listen = 1, ReuseAddr => 1, LocalPort => ..., ...); $ Клиент = $ socket-> принимать(); $ client-> sockopt (SO_LINGER, pack ('II', 1, 0)); закрыть $ client'. curl и wget всегда обрабатывают это условие с кодом возврата 56 и 4 соответственно. однако netcat недетерминированно обнаруживает «соединение, отклоненное сверстниками», но иногда нет. – bandie

ответ

1

Вы не указали точную ОС, которую используете. Я обнаружил, что у Linux есть вызов API, который сбросит TCP-соединение, я не знаю, насколько он портативен. Способ сделать это - использовать системный вызов connect на уже подключенном сокете, но на этот раз с семейством AF_UNSPEC.

После того, как вы сбросили сокет таким образом, можно снова подключить розетку с другим вызовом connect.

int main(int argc, char** argv) 
{ 
    int fd = socket(AF_INET6, SOCK_STREAM, 0); 

    while (1) { 
    struct sockaddr_in6 sockaddr = { 
     .sin6_family = AF_INET6, 
     .sin6_port = htons(80), 
     .sin6_flowinfo = 0, 
     .sin6_scope_id = 0, 
    }; 
    struct timespec s = { 
     .tv_sec = 2, 
     .tv_nsec = 0, 
    }; 

    /* Connect to port 80 on localhost */ 
    inet_pton(AF_INET6, "::1", &sockaddr.sin6_addr.s6_addr); 
    connect(fd, (struct sockaddr*)&sockaddr,sizeof(sockaddr)); 
    nanosleep(&s, NULL); 

    /* Reset previously connected socket */ 
    sockaddr.sin6_family = AF_UNSPEC; 
    connect(fd, (struct sockaddr*)&sockaddr,sizeof(sockaddr)); 
    nanosleep(&s, NULL); 
    } 
} 
+0

большой. Я протестировал ваше решение 'connect AF_UNSPEC' также в сценарии прослушивания ipv4, в этом случае мне нужно повторно подключить не к' listen'ing socket, а к возврату 'accept'. – bandie

Смежные вопросы