zaphoyd / websocketpp

C++ websocket client/server library
http://www.zaphoyd.com/websocketpp
Other
7.05k stars 1.97k forks source link

Websocketpp send() buffering messages #391

Open bkmnaidu opened 9 years ago

bkmnaidu commented 9 years ago

Hi, I am using webscoketpp library to connect to a server running on Windows from a client running on Ubuntu. I noticed that some of the sends from client are not received at the Server end immediately, but a group of the messages are received all at once (this is verified by running Wireshark to capture the packets of data on the wired interface). This indicates there is some weird buffering going on the client/Ubuntu side and I have changed the tcp_no_delay to 1. Even then, I do not see any change the behaviour.

Can anyone tell me how do I make sure the messages from the Client are received on the Server side without any buffering.

zaphoyd commented 9 years ago

When used with asynchronous transports (Like the bundled asio transport). send() is an async operation which queues a message to be sent and then returns. Calling send twice in a row in the same handler will result in two messages being queued. When the handler is over all queued messages will attempt to be sent. WebSocket++ will coalesce multiple outgoing messages into a single TCP packet if possible. If you want to ensure that every message gets written out as soon as possible, you have a few options.

The simplest is to issue one send and then use a timer or interrupt handler to yield control of the event loop back to the library for a bit so it can run some network operations. The timer/interrupt will call the original connection back and give it the opportunity to send some more.

An alternative method is to use two threads, one for issuing sends the other for processing network operations.

bkmnaidu commented 9 years ago

Thank you for you explanation. Is there some example code where I can see how to use this timer or interrupt handler in websocketpp.

Thanks in advance

zaphoyd commented 9 years ago

The telemetry_server example uses the timer method to remain responsive while providing server pushed telemetry in a single thread. The interrupt handler is not used, but it is semantically very similar to a timer with zero duration

crizCraig commented 7 years ago

The solution for me was to avoid printing messages to the console over RDP as this severely inhibits performance (i.e. threads wait for the remote message transfer of characters to the screen on the client side of the RDP session!).

vargss commented 7 years ago

Hi. I followed advice to use interrupt method in to break long handlers in pieces. I started with echo_server example. What I modified is listed below:

void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
        s->send(hdl, "some data", websocketpp::frame::opcode::text);
        s->interrupt(hdl);
        sleep(5);
        s->send(hdl, "some more data", websocketpp::frame::opcode::text);
        s->interrupt(hdl);
        sleep(5);
}
void on_interrupt(server* s, websocketpp::connection_hdl hdl)
{
    server::connection_ptr con = s->get_con_from_hdl(hdl);
    if (con->get_buffered_amount()==0)
    {
        return;
    }
    s->interrupt(hdl);
}

I also add this line in the in same place where all other handlers are set:

echo_server.set_interrupt_handler(bind(&on_interrupt, &echo_server,::_1));

Unfortunately, after reception of message, server sends both messages ("some data" and "some more data") only when whole on_message handler is finished. Furthermore, using std::cout I see that on_interrupt(...) is also called after finishing on_message. What am I missing?

zaphoyd commented 7 years ago

You are sending all of the data in on_message. To break it up using interrupt you need to call send in the interrupt handler. i.e.

on_message(...) {
    ...
    s->send(hdl, "some data", websocketpp::frame::opcode::text);
    sleep(5);
    s->interrupt(hdl);
}

on_interrupt(...) {
    ...
    s->send(hdl, "some more data", websocketpp::frame::opcode::text);
    sleep(5);
    if (!done) {    
        s->interrupt(hdl);
    }
}

You should see the first response after 5 seconds and subsequent ones every 5 seconds until done is true.

vargss commented 7 years ago

Thank you for your response!

With your example I get first message ("some data") after 10 seconds, then after 10 seconds I get three messages from on_interrupt() and then each 10 seconds I get additional two from on_interrupt(). Single message is never sent. What could be the cause?

alice-thorn commented 4 years ago

Hi, I am using webscoketpp library to connect to a server running on Windows from a client running on Ubuntu. I noticed that some of the sends from client are not received at the Server end immediately, but a group of the messages are received all at once (this is verified by running Wireshark to capture the packets of data on the wired interface). This indicates there is some weird buffering going on the client/Ubuntu side and I have changed the tcp_no_delay to 1. Even then, I do not see any change the behaviour. Can anyone tell me how do I make sure the messages from the Client are received on the Server side without any buffering.

I have exactly the same problem as you. I send message from c++ client running on Windows to a node.js server running on Windows every second, but the server receives 5 same messages at one time .Have you solved the problem?

erksch commented 4 years ago

I have the same problem. Using interrupt does not work somehow, the interrupt handler is not even called and no message is sent. Did you find a solution?

alice-thorn commented 4 years ago

Sorry ,I haven‘t found a solution.Interrupt didn't  work  in my program either.

------------------ 原始邮件 ------------------ 发件人: "erksch"<notifications@github.com>; 发送时间: 2019年12月16日(星期一) 晚上11:04 收件人: "zaphoyd/websocketpp"<websocketpp@noreply.github.com>; 抄送: "蓝精灵"<707836800@qq.com>;"Comment"<comment@noreply.github.com>; 主题: Re: [zaphoyd/websocketpp] Websocketpp send() buffering messages (#391)

I have the same problem. Using interrupt does not work somehow, the interrupt handler is not even called and no message is sent. Did you find a solution?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

flyerSon commented 4 years ago

i have the same problem

flyerSon commented 3 years ago

I read the code,maybe,you call write_frame() after call send_msg like this m_client.send(hdl, msg, websocketpp::frame::opcode::text, ec); std::cout << "send_msg " << (ec ? "error(" + ec.message() + ")" : "success") << " hd1: " << hdl.lock().get() << " message: " << msg << std::endl; if (auto con = m_client.get_con_from_hdl(hdl)) { con->write_frame(); }

danielab1 commented 3 years ago

i have the same problem

newpoo commented 1 year ago

I read the code,maybe,you call write_frame() after call send_msg like this m_client.send(hdl, msg, websocketpp::frame::opcode::text, ec); std::cout << "send_msg " << (ec ? "error(" + ec.message() + ")" : "success") << " hd1: " << hdl.lock().get() << " message: " << msg << std::endl; if (auto con = m_client.get_con_from_hdl(hdl)) { con->write_frame(); }

Is write_frame blocking?