Proposed change to Ethernet's write() / print() return value

Hi folks,

on the mailing list, there has been some discussion to change the value returned by the Ethernet library on write() or print() calls. Currently, these functions return the sum of the number of bytes written to all clients. So, if you print a five-byte string to the Ethernet object and one client is connected, it will return 5. If two clients are connected, it will return 10.

The proposal is to change this to return 5 in both cases, so that the returned value can be used for e.g. alignment of printed strings. The proposed implementation is to return the maximum number of bytes printed to each client (normally each client should have the same number of bytes printed, but they can be different in case of errors for example).

The main question of this post is: Is there anyone relying on the return value of Ethernet’s write() and print() for which this change would cause a problem?

For more details, see the original mailing list thread: http://comments.gmane.org/gmane.comp.hardware.arduino.devel/1928

This only applies to server.write(), server.print(), and server.println(), correct?

Yes, the same methods on a specific client will be unchanged.

That way you don't know to how many client your data was sent actually. What if you have 3 clients connected but the data was sent to only 2 of them? But to answer your question: I don't have existing code that is relying on that feature. I just think that the current implementation does make more sense.

pylon: That way you don't know to how many client your data was sent actually. What if you have 3 clients connected but the data was sent to only 2 of them?

I realize that you lose a bit of error reporting ability. However, if you need feedback on any sending errors and/or where your message was delivered, something better should be implemented instead. The old return value wasn't quite foolproof: What if you had two clients connected and (exactly) halfway through the data they both connect? The return value would indicate that enough characters are written for exactly one client, which could make you believe you succesfully sent to one client, while you actually sent half a message to two clients.

This is almost impossible as the whole message is sent in one packet. However you get exactly the same problems if you change the return value to your proposed version, you just loose a bit of information.

As Serial, EthernetClient, EthernetServer all use the stream library they should all adhere to it. Changing the rules to suit is a bad choice.

For instance, I should have no need to know what is further down the stream. Consider a throughput counter ( I just whipped one up ). It rely's on the rules outlined by the Stream definition, your mods would not return a correct measure of data sent and cause my code to fail. The main point is, changing a stream element can cause all elements higher than it to gracefully fail.

  enum TP_STREAM_ID{ TP_INPUT, TP_OUTPUT };
  
  class ThroughPut : public Stream{
  
    public:
      ThroughPut( Stream &s_Stream ) : stream( s_Stream ), DataIn( 0 ), DataOut( 0 ) { return; }
      
      int available( void ) { return stream.available(); }
      void flush( void ) { stream.flush(); }
      int peek( void ) { return stream.peek(); }
      
      unsigned int getCount( TP_STREAM_ID t_ID ) { return t_ID ? DataOut : DataIn; }
        
      int read( void ){
        int i_Return = stream.read();
        if( i_Return != -1 ) ++DataIn;
        return i_Return;
      }

      size_t write( uint8_t u_Data ){
        const size_t s_Return = stream.write( u_Data );
        DataOut += s_Return;
        return s_Return;
      }
      
    protected:
    
      Stream &stream;
      unsigned int DataIn;
      unsigned int DataOut;
  };

As Serial, EthernetClient, EthernetServer all use the stream library they should all adhere to it. Changing the rules to suit is a bad choice.

They do adhere to it and the proposed change would also. The Stream class doesn't say anything about how the result value is calculated when there are multiple listeners because usually there's only one consumer of a stream. In the case of the EthernetServer everything put out to the stream is sent to all connected clients and it's just a matter of definition if you want to return the amount of data sent to the stream or the amount of data sent out to the clients.

The main point is, changing a stream element can cause all elements higher than it to gracefully fail.

Please define why the proposed change will let your code fail. You might just measuring some other fact but the code will run without problems.

Please define why the proposed change will let your code fail. You might just measuring some other fact but the code will run without problems.

The code will run without problems, but will not show the number of bytes physically transmitted through the stream to its final destination. Just because there are multiple destinations, doesn't mean that each byte wasn't separately transmitted.

My throughput class wants to know what has been transmitted by the EthernetServer, not by an individual client of it, which my code knows nothing.

As the value is either 0 for fail or greater for something sent, it might as well contain something useful rather than a partial and unusable count of data transmitted, or more closely, the data transmitted down a single path of a potentially complex system.

I agree with you that the OP didn't provide enough reasons to cause a change in the current class but in my opinion your (partly) failing example is somewhat constructed. There are two possible views, both are legitim and both have good reasons for and against them, your's is just one them. I think the main reason to stay with the current implementation is that this way you don't loose information. The calling application is able to determine the number of clients connected. So it's also able to determine how many bytes each client received (given all were transmitted). In every other case you don't know what each client received but you can make some educated guesses with the current implementation, the proposed change would return 0 if just one of the clients didn't receive it's content although all the others got it right. That would be a loose of information and therefore I vote to leave it as it is.