[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [Libevent-users] Line-based evbuffer?



Yes! Thank you so much! For future reference I'm posting in my modified code, and I can verify that this at least works on the primitive example server.

void readcb(struct bufferevent *bev, void *ptr)
{
  struct evbuffer *input = bufferevent_get_input(bev);
  char *request_line;
  size_t len;

  while ( NULL != (request_line = evbuffer_readln( input, &len, EVBUFFER_EOL_CRLF ))){
    printf("<line>%s</line>\n", request_line ); fflush( stdout );
    free( request_line );
  }
}

int main(int argc, char **argv)
{
  /* ... */
  bufferevent_setcb(bev, readcb, NULL, NULL, base);
  /* ... */
}

Thanks a lot....Â


On Tue, Feb 2, 2016 at 3:13 PM, Azat Khuzhin <a3at.mail@xxxxxxxxx> wrote:
On Tue, Feb 2, 2016 at 4:32 PM, Ãystein SchÃnning-Johansen
<oysteijo@xxxxxxxxx> wrote:
> It is probably a misconception on my side. I'm pretty good at
> misconceptions. :-)
>
> To illustrate, I set up a really naive server in python:
>>>> import socket
>>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>>> s.bind(('', 8888))
>>>> s.listen(10)
>>>> while 1:
> ...  conn, addr = s.accept()
> ...  conn.send(b"Line 1\nLine 2\nLine 3\nLast line\n")
> ...  conn.close()

I use this:
$ nc -lp 8888 <<<$'line 1\nline 2'

> OK, then I code a simple client. (There are som short-cuts to avoid a lot of
> code, but this compiles and runs with -std=gnu99)
>
> #include <event2/dns.h>
> #include <event2/bufferevent.h>
> #include <event2/buffer.h>
> #include <event2/util.h>
> #include <event2/event.h>
>
> #include <stdlib.h>
> #include <stdio.h>
>
> void buffercb(struct evbuffer *input, const struct evbuffer_cb_info *info,
> void *ptr)
> {
> #if 1
>Â Â Âchar *request_line;
>Â Â Âsize_t len;
>
>Â Â Ârequest_line = evbuffer_readln( input, &len, EVBUFFER_EOL_CRLF );

Gotcha, buffercb() is a readcb of evbuffer, IOW it is invoked *every
time* you read from/to this *evbuffer*, see?
IOW when libevent calls buffercb(), buffercb() will call
evbuffer_readln(), and evbuffer_readln() also will call buffercb(),
and because of this recursion you have latest-first behavior.

>Â Â Âif ( request_line ){
>Â Â Â Â Âprintf("%s\n", request_line ); fflush( stdout );
>Â Â Â Â Âfree( request_line );
>Â Â Â}
> }
>
> int main(int argc, char **argv)
> {
>Â Â Âstruct event_base *base;
>Â Â Âstruct evdns_base *dns_base;
>Â Â Âstruct bufferevent *bev;
>
>Â Â Âif( argc != 3 ){
>Â Â Â Â Âprintf("Usage: %s host port", argv[0]);
>Â Â Â Â Âreturn -1;
>Â Â Â}
>
>Â Â Âbase = event_base_new();
>Â Â Âdns_base = evdns_base_new(base, 1);
>
>Â Â Âbev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
>Â Â Âbufferevent_setcb(bev, NULL, NULL, NULL, base);
>Â Â Âbufferevent_enable(bev, EV_READ|EV_WRITE);
>Â Â Âbufferevent_socket_connect_hostname(
>Â Â Â Â Âbev, dns_base, AF_UNSPEC, argv[1], atoi(argv[2]));
>
>Â Â Âevbuffer_add_cb( bufferevent_get_input(bev), buffercb, NULL );

That's why it is better to use "readcb" over bufferevent that
installed via bufferevent_setcb() instead of callbacks over evbuffer.

Of course you can remove that callback in buffercb(), and translate
that evbuffer_readln() into loop, but this is not how things should
work.

>
>Â Â Âevent_base_dispatch(base);
>Â Â Âreturn 0;
> }
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users  in the body.