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

Re: [Libevent-users] unsend data in output buffer when close connection



On Fri, Jan 16, 2015 at 03:42:49PM +0800, slump wrote:
> 
> I have used bufferevent to send data to socket
> the application use variable length message, the first 4 bytes in message is the length
> 
> all thing is OK but for socket reconnect
> 

You should always free the bufferevet when a client terminates a
connection. Though there is an exception which you point out that
can happen, and I've noticed more kernels actually utilizing it.

> if the socket is closed by peer and my app reconnect
> peer may receive the wrong msg, the message length is  wrong
> 

I honeslty have no idea how you're using th same bufferevent for a new
connection, are you just re-using the same thing?

> it seems the unsent data in bufferevent's output buffer will be send when the socket reconnect
> but the message boundary is broken in output buffer
> 
> I guess it is because when I write message use bufferevent_write, one message is splited into two chunks in output buffer
> one chunk is send to peer before socket closed
> and the  next chunk is sent to peer after socket reconnect, so the message is broken
> 

So we all know the handshake that happens duringa proper socket close,
fin, fin-ack, fin. But optionally, the server or client (and whether the
kernel accepts such a thing), a fin can still contain data if everything
is shutdown properly.

But even in the case of an immediate reconnect, once the final ack of
the handshake should mark the client socket invalid, and whatever event
system you are using; epoll, kqueue, select, /dev/poll, poll, or that
windows thing I know nothing about should immediately return. 

Another question: are you using the edge-triggered option? 

> if it is true, can I get the data from output buffer and find the next message begin in data
> so I can  discard the broken message and send the message follow it

1. Are you using the connlistner API? If so you can set error callbacks,
not just standard flag based event notifications.

If not:

2. Are you setting the event callback and or including deferred? I'm not
quite sure how this condition can actually happen in any shutdown
condition. Are you able to prototype up an application that can reproduce
this condition, using the same flags and setup?

To be perfectly honest, this sounds more like a design flaw in the
application itself, you should get an event callback where you can 
check for an error, or even a recv() that would return -1 upon error.
 
Are you sure you're not mixing up size_t and ssize_t?.

If you want to continue down the road of flawed design:

* some sort of identifier for a client which you can keep track of and
  discard if it's not the client you expected.

* don't reuse bufferevents for new connections?

> but I find I can't get the data from output buffer, the evbuffer_copyout function return -1
> 

evbuffer_remove? But still, this requires the re-use of a single
bufferevent.

> and I can't find the function to clear the output buffer to discard all message in buffer
> 

get the output buffer from the bufferevent, then evbuffer_drain()

> the only thing I can do is to free the bufferevent and create a new bufferevent when reconnect socket
> 
> is it the right way to do such thing?
> 

IMO, it's the safest way, especially in your situation, I'd really
consider using evconnlistener.
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.