[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [Libevent-users] socket message boundary problem
Hi Nick:
Thank your for your advice.
Regards
YHM
On Thu, Jun 3, 2010 at 11:51 PM, Nick Mathewson <nickm@xxxxxxxxxxxxx> wrote:
> On Mon, May 31, 2010 at 1:14 PM, Hor Meng Yoong <yoonghm@xxxxxxxxx> wrote:
>> Hi:
>>
>> I am using libevent2. Is that a wrapper function/library to send and
>> receive fixed length message, or variable length message with message length
>> embedded in the first 2 bytes with libevent2? Thank
>
> Got all three of your messages. No need to send so many!
>
> There's no built-in function to do this, but it's very easy to do with
> bufferevents. Here's some example demo code to show you the general
> idea of how it's done:
>
>
> #include <event2/bufferevent.h>
> #include <event2/buffer.h>
>
> #define MSG_LEN 512
>
> int
> send_fixed_msg(struct bufferevent *bev, const char *msg)
> {
> bufferevent_write(bev, msg, MSG_LEN);
> return 0;
> }
>
> void
> fixed_msg_readcb(struct bufferevent *bev, void *ctx)
> {
> char msg_buf[MSG_LEN];
> struct evbuffer *inp = bufferevent_get_input(bev);
> while (evbuffer_get_length(inp) >= MSG_LEN) {
> evbuffer_remove(inp, msg_buf, MSG_LEN);
> /* Here's where you add code to handle the contents of
> * msg_buf */
> }
> }
>
> void
> setup_fixed_msg_bufferevent(struct bufferevent *bev)
> {
> /* Set up the read callback to be invoked when we have some bytes that
> have arrived. In practice, you'd also want to set the other
> callbacks, and maybe provide some data too. */
> bufferevent_setcb(bev, fixed_msg_readcb, NULL, NULL, NULL);
> }
>
>
> /* Now, variable-length messages. Let's assume that the message format
> * is a two-byte length value encoded in big-endian (network) order,
> * plus that number of bytes worth of message */
> int
> send_var_msg(struct bufferevent *bev, const char *msg, int length)
> {
> ev_uint16_t len_encoded;
> if (length < 0 || length > 65535)
> return -1;
> len_encoded = htons(length);
> bufferevent_write(bev, &len_encoded, 2);
> bufferevent_write(bev, msg, length);
> return 0;
> }
>
> void
> var_msg_readcb(struct bufferevent *bev, void *ctx)
> {
> struct evbuffer *inp = bufferevent_get_input(bev);
> char msg_buf[65536];
> ev_uint16_t len_encoded;
> int msglen;
> while (1) {
> int len_in_buf = evbuffer_get_length(inp);
> if (len_in_buf < 2)
> return;
> /* We have enough data to read a length field. For now,
> * just inspect it but don't remove it.
> */
> evbuffer_copyout(inp, &len_encoded, 2);
> msglen = ntohs(len_encoded);
> if (len_in_buf < 2 + msglen) {
> /* The entire message hasn't arrived yet. */
> return;
> }
> /* The message is here; pull it out of the buffer. */
> evbuffer_drain(inp, 2); /*discard the length field */
> evbuffer_remove(inp, msg_buf, msglen);
>
> /* Here's where you add code to handle the contents of
> * msg_buf */
> }
> }
>
> void
> setup_var_msg_bufferevent(struct bufferevent *bev)
> {
> /* Set up the read callback to be invoked when we have some bytes that
> have arrived. In practice, you'd also want to set the other
> callbacks, and maybe provide some data too. */
> bufferevent_setcb(bev, var_msg_readcb, NULL, NULL, NULL);
> }
>
>
>
> Note that in practice you might want to use watermarks to avoid
> extraneous calls to the _readcb functions. For more info on the
> bufferevent API, check out chapter Ref6 of
> http://www.wangafu.net/~nickm/libevent-book/ .
>
> hope this helps,
> --
> Nick
> ***********************************************************************
> To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
> unsubscribe libevent-users in the body.
>
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users in the body.