[Boost-bugs] [Boost C++ Libraries] #6661: Different behavior on WIN and Linux

Subject: [Boost-bugs] [Boost C++ Libraries] #6661: Different behavior on WIN and Linux
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2012-03-08 07:58:05


#6661: Different behavior on WIN and Linux
-------------------------------------+--------------------------------------
 Reporter: cupper.jj@… | Owner: chris_kohlhoff
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: asio
  Version: Boost 1.49.0 | Severity: Problem
 Keywords: udp, available, receive |
-------------------------------------+--------------------------------------
 Hi, I've found a different behavior at use of some functions with UDP
 protocol.

 Look at this code

 {{{
         io_service ios;

         udp::endpoint to(address::from_string("127.0.0.1"), port);
         udp::socket sender(ios, udp::v4());
         udp::socket receiver(ios, udp::endpoint(udp::v4(), port));

         const char buf[] = "Some test data...";
         const size_t buf_len = sizeof(buf);

         char read_buf[buf_len];
         char half_read_buf[buf_len / 2];

         sender.send_to(buffer(buf, buf_len), to);
         try
         {
                 udp::endpoint sender_point;
                 receiver.receive_from(buffer(half_read_buf,
 sizeof(half_read_buf)),
 sender_point);
         }
         catch(exception& ex)
         {
                 string str = ex.what();
                 cerr << "Exception: "<< ex.what() << endl;
         }
         cout << string(half_read_buf, sizeof(half_read_buf)) << endl;

         sender.send_to(buffer(buf, buf_len), to);
         sender.send_to(buffer(buf, buf_len), to);

         cout << "Available: " << receiver.available() << endl;
         receiver.receive(buffer(read_buf, sizeof(read_buf)));

         cout << "Available: " << receiver.available() << endl;
         receiver.receive(buffer(read_buf, sizeof(read_buf)));

         cout << "Available: " << receiver.available() << endl;
 }}}

 Here we are reading half an datagramm and use socket::available() to look
 how much data into the socket.
 Execute this code on WIN32 and you get this output

 {{{
 Exception: receive_from: The message was too large for the specified
 buffer and (for unreliable protocols only) any trailing portion of the
 message that did not fit into the
 buffer has been discarded.
 Some test
 Available: 36
 Available: 18
 Available: 0
 }}}
 Execute it on Linux and you get

 {{{
 Some test
 Available: 18
 Available: 18
 Available: 0

 }}}

 It looks strange.[[BR]]
 Look into source

 {{{
 boost/asio/detail/impl/socket_ops.ipp
 -------------------------------------
 int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
     socket_addr_type* addr, std::size_t* addrlen,
     boost::system::error_code& ec)
 {
 ...
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
   int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
         &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
   *addrlen = (std::size_t)tmp_addrlen;
 ...
   if (result != 0)
     return socket_error_retval;
   ec = boost::system::error_code();
   return bytes_transferred;
 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
   msghdr msg = msghdr();
   init_msghdr_msg_name(msg.msg_name, addr);
   msg.msg_namelen = *addrlen;
   msg.msg_iov = bufs;
   msg.msg_iovlen = count;
   int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
   *addrlen = msg.msg_namelen;
   if (result >= 0)
     ec = boost::system::error_code();
   return result;
 }
 }}}
 For WIN32 uses functions family WSARecv([http://msdn.microsoft.com/en-
 us/library/windows/desktop/ms741686(v=vs.85).aspx]) they return status of
 error. And one of which is

 {{{
 WSAEMSGSIZE
 The message was too large for the specified buffer and (for unreliable
 protocols only) any trailing portion of the message that did not fit into
 the buffer has been discarded.
 }}}

 For Linux uses functions family recv ([http://linux.die.net/man/2/recv]).
 They return the length of the message on successful completion or -1 and
 set status in errno if was error. But for them no the error if buffer
 length less that a received datagram.[[BR]]

 But if we uses function recvfrom, it sets this error into struct msghdr in
 the msg_flags

 {{{
 MSG_TRUNC
 indicates that the trailing portion of a datagram was discarded because
 the datagram was larger than the buffer supplied.
 }}}

 And also about function basic_datagram_socket::available. For WIN32 it
 returns length of all datagrams in the socket BUT for linux in returns
 length a one datagramm.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/6661>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:09 UTC