Libevent: как временно отключить, а затем снова включить EV_READ? (В С)

Я использую libevent для обработки получения данных на наборе портов. Поведение, которое я хотел бы выполнить, таково:

-Скажем, у меня есть набор портов, 1001-1004 -Чтение данных по порту, скажем, 1001. -Как только будет выполнен обратный вызов, отключите дальнейшее чтение на этом порту (1001). -После того, как все порты получили данные, снова включите их для чтения.

Сейчас у меня есть структура буферных событий:

static struct bufferevent *bev[4];

Я настроил слушателей, как показано в документации:

/* Listener 1 */
sin.sin_port = htons(MIXPORT + 1);
listener1 = evconnlistener_new_bind(base, accept1, NULL,
    LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
    (struct sockaddr*)&sin, sizeof(sin));
if (!listener1) { perror("Couldn't create listener1"); return 1; }
evconnlistener_set_error_cb(listener1, accept_error_cb);

static void accept1(struct evconnlistener *listener,
evutil_socket_t fd, struct sockaddr *address, int socklen,
void *ctx) {
/* A new connection was received on this port */
struct event_base *base = evconnlistener_get_base(listener);
bev[0] = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);

/* Callback for when (*bufevent, data READ, data WRITTEN, event OCCURRED, *void) */
bufferevent_setcb(bev[0], read1, NULL, echo_event_cb, NULL);

/* Set bufferevent to be able to read */
bufferevent_enable(bev[0], EV_READ);
}

Затем я дал ему обратный вызов READ:

static void read1(struct bufferevent *bev, void *ctx) {
if(LOG) { logoutput("Data received on port 1"); }

struct evbuffer *input = bufferevent_get_input(bev);
size_t len = evbuffer_get_length(input);
data[0] = malloc(len);

/* Copy evbuffer data into array */
evbuffer_copyout(input, data[0], len);
/* Remove data from evbuffer after copying it out */
evbuffer_drain(input, len);

handle(0);
}  

В моей функции "handle" я сказал ей сделать это:

static void handle(int i)
{
/* Disable reading on port until re-enabled later */
bufferevent_disable(bev[i], EV_READ);  // I thought this should do it?!

// Do other stuff...
random_function();
}

И наконец...

static void random_function(); {
/* Re-enable read on port */
    bufferevent_enable(bev[src], EV_READ);
}

Любые идеи, что я делаю неправильно? Когда я отправляю данные на случайный порт, я все еще могу отправлять их все больше, больше и больше.
TIA!


person Chris C    schedule 19.10.2012    source источник


Ответы (1)


Похоже, вы просто отключаете чтение данных в сокете, но это не помешает кому-то отправить вам данные в этот сокет (ОС будет буферизовать изрядное количество данных от них, потому что предполагает, что вы захотите прочитать это когда есть время).

Вы не можете запретить им отправлять данные, но вы можете остановить новые подключения к этим портам (не принимая подключения к заблокированным портам, пока вы не захотите этого снова), и вы можете закрыть подключения к вашим закрытым портам, если они отправляют вам данные. (это будет означать, что вы все еще хотите читать эти порты, но если они вам что-то отправят, вы close() их или что-то в этом роде.)

person hexist    schedule 19.10.2012
comment
Спасибо за помощь! Хм... Я понимаю, что вы говорите, но поскольку я делаю это на C, становится очень сложно закрыть порт, так как это убивает прослушиватель событий, и все эти вещи должны быть переделаны. Я также нашел evconnlistener_disable(), который, кажется, то, что я хочу: эти функции временно отключают или снова включают прослушивание новых соединений. Но во время тестирования это фактически не препятствует успешному выполнению функции connect(). - person Chris C; 20.10.2012
comment
Хорошо, я придумал способ сделать это. Я собираюсь бросить все свои материалы по созданию событий в функцию и вызывать ее при запуске. Затем, когда я получу обратный вызов, я вызову evconnlistener_free() для этого события прослушивателя. Это освобождает событие и закрывает сокет. Затем, когда я буду готов снова включить все, я просто снова вызову свой материал для создания событий. Спасибо! - person Chris C; 20.10.2012