Questions about RPC, etc.
by Ken Brooks · in Torque Game Engine · 06/09/2004 (12:42 pm) · 7 replies
1. The NetInterface connection scheme seems to happen all rather invisibly. On the server side, supposing I would like to give the user some encouraging sign when a client connects. How can I get the information that a connection has taken place? How can I get and display the IP address of the connecting client?
2. The documentation gives a list of basic argument types that RPC can handle. Can I make it handle a big struct, or other thing that will respond properly to sizeof() ? Which place in the documentation should I have been reading to address this question?
3. The simple example uses an RPC argument of type char *. I am astonished. How can a simple macro recognize that this argument cannot use sizeof(), but must use strlen() or something of the sort to determine the amount of data to be sent? (I looked at the preprocessor output, but it is too deep for me.)
4. When building a client-only program, I got link errors when I left off the RPC methods. I found that I had to define dummy implementations for them. Is this right? How can I be confident that the remote implementations, and not the local implementations, will be called?
2. The documentation gives a list of basic argument types that RPC can handle. Can I make it handle a big struct, or other thing that will respond properly to sizeof() ? Which place in the documentation should I have been reading to address this question?
3. The simple example uses an RPC argument of type char *. I am astonished. How can a simple macro recognize that this argument cannot use sizeof(), but must use strlen() or something of the sort to determine the amount of data to be sent? (I looked at the preprocessor output, but it is too deep for me.)
4. When building a client-only program, I got link errors when I left off the RPC methods. I found that I had to define dummy implementations for them. Is this right? How can I be confident that the remote implementations, and not the local implementations, will be called?
About the author
#2
> 2. The RPC code cannot handle arbitrary structs -- yet. There will be a types library at some point that will allow users to add new types for recognition by the RPC system.
Does that mean I have to drop down to the NetEvent level to send a big block of data? Or is there some other block-data approach within the RPC level? That would be really nice, even if I have to just give you a void* pointer and byte count.
Ken
06/10/2004 (5:15 am)
Mark Frohnmayer said:> 2. The RPC code cannot handle arbitrary structs -- yet. There will be a types library at some point that will allow users to add new types for recognition by the RPC system.
Does that mean I have to drop down to the NetEvent level to send a big block of data? Or is there some other block-data approach within the RPC level? That would be really nice, even if I have to just give you a void* pointer and byte count.
Ken
#3
06/10/2004 (8:08 am)
ByteBufferRef is a supported type. Bear in mind that the system will puke if you try to send more than a packet's worth of data in one RPC. Better to break long structures into many RPC calls. This approach also avoids endian issues.
#4
06/10/2004 (2:54 pm)
ByteBufferRef's are the way to go. If I recall, the RPC stuff maxes out at 1024 byte ByteBuffers, so you'll need to break it down to that level.
#5
I've checked that the serialization and unserialization of my classes are identical, so I figured I'd ask some people who knew more than I :-)
According to tnlRPC.h in version 1.5, ByteBufferPtrs are supported by RPCs, but ByteBufferRefs aren't.
What is the proper way to send ByteBuffers over an rpc?
Thanks a lot for your time :-)
--Ben
11/04/2005 (2:40 pm)
I had a follow up question on this topic if you guys have time. I'm looking into transferring arbitrary classes over TNL, and have a way to serialize them to ByteBufferPtrs. Passing them to an rpc is fine at compile time, but when debugging, the ByteBufferPtr that comes through looks to be garbage memory, while all the other parameters transferred through the rpc are fine.I've checked that the serialization and unserialization of my classes are identical, so I figured I'd ask some people who knew more than I :-)
According to tnlRPC.h in version 1.5, ByteBufferPtrs are supported by RPCs, but ByteBufferRefs aren't.
What is the proper way to send ByteBuffers over an rpc?
Thanks a lot for your time :-)
--Ben
#6
While I realize this post is nearly 1 year old, I just ran into the same issue. I am not sure if this was Ben's actual problem, but it is a possibility. I doubt this reply will help Ben, but it may help some future TNL user ;)
Things to keep in mind:
- ByteBufferPtrs are indeed the correct way to send raw data by RPC. ByteBufferRefs are no longer supported in the current CVS.
- The ByteBuffer class has a bool flag, mOwnsMemory.
My problem was the following: My ByteBuffers were being created with mOwnsMemory = false (the default option). My serialization class was managing the memory. The serialization class was DEALLOCATING the memory before the raw bytes were transmitted. This is the 'garbage memory' that is being received on the remote end of the connection.
My solution was to have my serialization class return a copy of it's buffer. I then create a ByteBuffer, and set mOwnsMemory = true. I am now free to deallocate my serialization class, and the ByteBuffer will manage it's own memory.
A way to pretty much guarantee that this is your issue is to examine the remote ByteBuffer. If the remote ByteBuffer::getBufferSize() returns the correct value (as set locally by your serialization class), then the above solution will probably fix your problem.
08/29/2006 (11:07 am)
Quote:I had a follow up question on this topic if you guys have time. I'm looking into transferring arbitrary classes over TNL, and have a way to serialize them to ByteBufferPtrs. Passing them to an rpc is fine at compile time, but when debugging, the ByteBufferPtr that comes through looks to be garbage memory, while all the other parameters transferred through the rpc are fine.
I've checked that the serialization and unserialization of my classes are identical, so I figured I'd ask some people who knew more than I :-)
According to tnlRPC.h in version 1.5, ByteBufferPtrs are supported by RPCs, but ByteBufferRefs aren't.
What is the proper way to send ByteBuffers over an rpc?
Thanks a lot for your time :-)
--Ben
While I realize this post is nearly 1 year old, I just ran into the same issue. I am not sure if this was Ben's actual problem, but it is a possibility. I doubt this reply will help Ben, but it may help some future TNL user ;)
Things to keep in mind:
- ByteBufferPtrs are indeed the correct way to send raw data by RPC. ByteBufferRefs are no longer supported in the current CVS.
- The ByteBuffer class has a bool flag, mOwnsMemory.
My problem was the following: My ByteBuffers were being created with mOwnsMemory = false (the default option). My serialization class was managing the memory. The serialization class was DEALLOCATING the memory before the raw bytes were transmitted. This is the 'garbage memory' that is being received on the remote end of the connection.
My solution was to have my serialization class return a copy of it's buffer. I then create a ByteBuffer, and set mOwnsMemory = true. I am now free to deallocate my serialization class, and the ByteBuffer will manage it's own memory.
A way to pretty much guarantee that this is your issue is to examine the remote ByteBuffer. If the remote ByteBuffer::getBufferSize() returns the correct value (as set locally by your serialization class), then the above solution will probably fix your problem.
#7
08/29/2006 (11:23 am)
That is absolutely Genius!
Associate Mark Frohnmayer
void GameConnection::onConnectionEstablished() { Parent::onConnectionEstablished(); if(isInitiator()) logprintf("Connected to server at address %s.", getNetAddressString()); else logprintf("Client at address %s connected.", getNetAddressString()); }2. The RPC code cannot handle arbitrary structs -- yet. There will be a types library at some point that will allow users to add new types for recognition by the RPC system.
3. The RPC system parses the argument list to the function as a string. Pretty cool, eh? :)
4. Yes, you have to define implementations for all RPC methods, even if they are empty. See the Master server and master clients for examples of this. The master server works, so hopefully that will give you all the confidence you need that your program will work too :)
- Mark