Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Dynamism at Packet class again  (Read 3799 times)

0 Members and 1 Guest are viewing this topic.

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
Dynamism at Packet class again
« on: October 13, 2011, 07:55:48 pm »
I find sf::Packet not dynamic enough.

There is a public Append function to append any number of bytes from a void*, but the reverse operation isn't provided, making this function quite useless: There isn't a good way to read some number of bytes into an array.

We may say: Packet is for structured data only, there is no need to mix unstructured data with structured one. In this case Append shouldn't be public to start with. Though there are situations where it may be useful. Examples are image bytes and sound samples, but even assuming that we can stream them directly through Packet ojects (which we currently can't), there are other sistuatios. Some silly example may be transferring information of a tile-set based level to other peers that doesn't have it yet, the level may have some structured information like name and other properties, and a matrix of bytes (because there are no more than 256 tiles for instance). It makes sense to append the whole array at once instead of one cell at a time, because it will avoid unnecessary resizes of the internal vector of Packet, and many internal calls to memcpy.


Example:
Code: [Select]

// Write
char* myData = ... ;
std::size_t myDataSize = ... ;
// write some structured data before, like a header
packet << ... ;
// write some unstructured data
packet.Append(myData, myDataSize);
// write some more structured stuff
packet << ... ;

(...)
// Read
// Read some structured data before, like a header
packet >> ... ;
// read some unstructured data
???
// read some more structured stuff
packet >> ... ;


The first alternative that comes to mind is to use GetData() + offset, and do a memcpy to our array. The first possible obstacle is the need to compute the offset, i.e. the number of bytes of structured data already read, since there isn't a function to obtain the reading position.
The second obstacle can't be overpassed: after obtaining our unstructured data, there is no way to move the reading position of the packet, to read the structured data that comes next.

The second alternative that comes to mind is to only use raw data. Then we don't need a Packet, we send/receive directly from/to char* on the socket, but we must re-implement the structured streaming just like on Packet.

-------------------

A different possible problem is when we want to send the same data to many peers, only differing in few bytes (like header information). With packet we need to copy the whole information for every peer because we don't have random access to modify the header.
The silly workaround is using a packet object just to build up the serialized data and copy it only once into a byte array, leaving space at the beginning for the header. For every peer we use another packet to build the header, copy the resulting data into the beginning of the byte array. Finally we send the byte array directly through the socket.


This is one reason (but not the main one) of why I asked in some other topic about InputStream and OutputStream classes for data serialization, in replacement of sf::Packet, which is tied to the network.
Currently Packet can still be used as a serialization tool, even that it is not supposed to. We can serialize our structures into a packet, use GetData to obtain the serialized data and save it to somewhere else (ex: a file). And one can fill a Packet with data from somewhere else (ex: file) by using the Append function, and then use the >> operators to deserialize the information into our structures. This is silly, but is an alternative to creating our own Input/Output stream classes or using other serialization system.

True generic streaming may be too much for SFML, but instead of Packet we could have had a class to serialize/deserialize data to/from a byte array for example, pretty much like how Packet class currently works.
In particular, sockets could receive an OutputStream when Sending, and provide an InputStream when receiving, so it works exactly as Packet did, we just untied the serialization functionality from the network package.
This is different from the current InputStream, but it could be combined/merged somehow.


Sorry for the long post and for insisting on this, but whenever I start coding with SFML I feel like having to do many workarounds for things that were supposed to be simple, or for things that I feel being partially supported. I don't feel like using other more complex and specialized tools, because things like basic serialization is provided, it's just that it's tied to the network.
Pluma - Plug-in Management Framework

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Dynamism at Packet class again
« Reply #1 on: October 14, 2011, 07:59:47 am »
You're absolutely right. Unfortunately I won't be able to redesign sf::Packet (and potentially an OutputStream class) for SFML 2.0. I'll definitely try to improve it, but I'll have to keep API compatibility so it may be limited.

I'll add an issue about that in the task tracker.

Thanks for your feedback, and for insisting on this important feature ;)
Laurent Gomila - SFML developer

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
Dynamism at Packet class again
« Reply #2 on: October 14, 2011, 08:13:56 pm »
Quote from: "Laurent"
I'll have to keep API compatibility.

Compatibility with SFML 1.x? I thought it wasn't an issue.

The design of the new API is probably the most important on SFML 2.0, because of the next 2.x versions. It may be worthwhile redesigning this for 2.0+ even if it isn't fully implemented yet.
It isn't a priority obviously, but you can think about it after completing the graphics API.
Pluma - Plug-in Management Framework

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Dynamism at Packet class again
« Reply #3 on: October 14, 2011, 08:45:26 pm »
Quote
Compatibility with SFML 1.x? I thought it wasn't an issue.

No, compatibility with 2.x. If it's not done in SFML 2.0, any modification which breaks API compatibility will have to be postponed to SFML 3.
Laurent Gomila - SFML developer

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
Dynamism at Packet class again
« Reply #4 on: October 14, 2011, 09:18:27 pm »
Ok I understand that you don't want to delay 2.0 more.
I'll stick with annoying workarounds for now.

Edit: Thanks for the issue on the task tracker, it captures the essential points  :wink:
Pluma - Plug-in Management Framework

 

anything