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()


telnet-ing to this will send back
Line 1
Line 2
Line 3
Last Line

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 );
    if ( request_line ){
        printf("%s\n", request_line ); fflush( stdout );
        free( request_line );
    }
#else
    char buf[1024];
    int n;
    while ((n = evbuffer_remove(input, buf, sizeof(buf))) > 0) {
        fwrite(buf, 1, n, stdout);
    }
#endif
}

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 );

    event_base_dispatch(base);
    return 0;
}

If I compile that code and run it against the python server, I get:

$ ./testclient localhost 8888

Last line

Line 3

Line 2

Line 1

How come? I still think the problem is in my conception of the buffer. At
least, I can still not get it working as expected with evbuffer_readln().
:-)

Thanks,


On Tue, Feb 2, 2016 at 12:54 PM, Azat Khuzhin <[email protected]> wrote:

> On Tue, Feb 2, 2016 at 1:50 PM, Øystein Schønning-Johansen
> <[email protected]> wrote:
> > Thanks, I'm aware of that function. However, the reads from the socket
> comes
> > in with several lines at a time and the buffer does not necessarily begin
> > with the start of a new line or end at the end of a line. In these cases
> the
>
> Even if it will end with new line, no guarantee that you will receive
> this like the sender send, since this is network and you have
> non-blocking IO.
>
> > callback handler will handle the last full line first. I'm not sure if
> this
> > is a bug in evbuffer_readln() or not?
>
> I'm not sure that I understand you, it can't work like this,
> it must process buffer from begin->end not in the reverse order.
>
> Can you please provide a sample, that will show this behavior?
>
> And of course evbuffer have buffering, IOW if you have something like this:
> recv(4, "foo")
> recv(4, "bar\n")
>
> Then evbuffer_readln() will return "foobar\n", and will return empty
> if you will call it between this two recv().
>
> Am I missing something?
> ***********************************************************************
> To unsubscribe, send an e-mail to [email protected] with
> unsubscribe libevent-users    in the body.
>

Reply via email to