Since the combined length of - say - filenames in a directory can vary a lot, serialization is a good idea.
On the sender side you could make use of an RBufWriteStream with a CBufFlat. After serialization, you know the length, that is what you should send to the receiver side first:
Of course this code is nasty, because using User::WaitForRequest blocks your whole application. So in reality and active object should be used, but for testing purposes the code actually works, and it is more readable this way.
// serialize your data here
CleanupStack::PopAndDestroy(); // stream
TPckgBuf<TInt> size; // TPckgBuf is a 8-bit descriptor, containing an instance of the type specified as the template argument
size()=buf->Size(); // TPckgBuf::operator() provides access to the contained object
CleanupStack::PopAndDestroy(); // buf
On the receiver side you get "size" first, then you should read exactly the same amount of data from the socket. It is tricky a bit, because creating a descriptor of specified size in runtime is a bit tricky:
Or an alternative would be RecvOneOrMore-ing in a loop, and collecting the data (in a CBufFlat for example) until the specified length has been reached.
HBufC8 *buf=HBufC8::NewLC(size()); // this line allocates a descriptor which can contain the specified size, but it can be larger in fact
TPtr8 ptr( const_cast<TUint8*>(&(*buf)), size()); // there are a number of equally ugly approaches you could choose from
// deserialize your data
CleanupStack::PopAndDestroy(2); // stream, buf