Sending objects via high speed asynchronous sockets in C# (Serialization + Socket programming)
DISCLAIMER
Some users at stackoverflow found bugs in this implementation, see the rightful complaints here. As it stands now this code will not handle sending data that is larger than 1 packet correctly. You will have to implement some sort of protocol to handle this to replace the wrong check that there is now that just keeps reading if a full packet was received. It also doesn’t close the client-socket properly when everything is done. Leaving that to the client which can be forgotten. I would like to thank the stackoverflow user Polity for posting here to bring the bugs to my attention!
You can find a new updated version here that fixes all these problem, has been brought up-to-date and includes the source code. I’ll keep this old article here for reference, but please use the new article when you’re actually building something!
END DISCLAIMER
Well a while has past since my last useful post here, but here I am at it again a post filled with useful source code to use in your everyday C# programs.
I was very curious how games work with async sockets to keep everyone communicating smoothly so I set up a simple test app to test async sockets in C#, however this seemed quite a bit harder than I thought and after some help at the Dutch website tweakers.net I finally had everything working. (I finally figured out that I shouldn’t be using the beginsendpacket but the beginsend methods). Anyway let’s get straight to business.
I first made a small object that we want to send over the network, let’s call it Status, below is the source code for that object, let’s make a couple of stuff clear.
As you can see the class is marked serializable with [Serializable] this signals the compiler that we should be able to serialize this object. (Get it from memory, place it in a byte array and send it anywhere (harddrive/network/etc..). Stuff that shouldn’t be send with it like external classes that we would like to send later should be marked [NonSerialized] (the Java equivalent for transient). This way we can cut of some dependencies and keep the overhead low. (For example no matter what the TransmissionBuffer referenced to, because it’s nonserialized it’s reference will not be send aswell and it will appear on the other side as “null”.
As you can see the only real data this object hold is a small string called msg the other objects are for administrative purposes as we will see soon.
Now there are allot of examples out there that show how to send a string, you can easily get the bytearray from a string and send it anywhere, for an object that is slightly harder, as you can see in the serialize() method we have to create a binarrayformatter, this binarray formatter is then fed a direct stream to the memory where our object resides and a reference to our memorystream, the object is serialized in our memorystream’s buffer as a bytearray and then we can do anything we want with it. This method just returns the buffer so we can set it over a network. The deserialize method does exactly the same but then the other way arround except for the mem.Seek(0,0); we see right before return, this seek sets the pointer of the stream at the start of the stream so the binarrayFormatter can start reading and deserializing from the start of the stream. (Forgetting this would give an error telling that the end of the stream was found before deserialzing was completed, which makes sence if you think about it).
Anyway before we get to the real workhorse of the code let’s take a look at the client.
Don’t mind the manualreset events to much, they’re there so the application doesn’t go to fast so we can see what happens instead of 2 console windows just printing text like mad :). (Remember that they will send as fast as possible because they are asynchronous and don’t have to wait for the first send to complete so yeah some pause points are quite handy for now, in a real client you wouldn’t use while(true) but something more sophisticated like an update interval or when something changed.
As you can see the start method creates a socket and tries to send some data nothing super special here except for that the beginconnect method references the connect method. When the server is ready for a connection the connect method is executed, we create a new status object and place the socket we get returned from the endAccept method in there for bookkeeping (we need it later to send data else we don’t know which socket we where using, this is also why the socket is [unserialized] we don’t need to send it the other way). We also fill the msg of the object and then serialize it to a byte array, we place that bytearray in the beginsend method.
When the server is ready for receiving data the Send method is called. This method uses the socket in the packet to call endsend and read how many bytes where send.
And now, the server!
Well start and accept basically do the same as the client but then the other way around, the only big difference we have is the receive method which endreceives() the data, but it’s not done yet, first it has to check if all the bytes where received if not we have to put the object in a listening state again to get the rest of the bytes from the networkcard. Then when all the bytes are safely inside our Transmissionbuffer we deserialize our object and print the msg we place in it.
Allot of work to just send a string accros, but this code will work any object and make your server nonblocking which could make it much faster, just instead of putting “string msg” in your status object put “TheObjectYouWant obj” in your status object and you are free todo as you please.
Feel free to ask questions and comments, the full sourcecode is available here: AsyncSocketServer+Client.rar
- roytries
- roy-t
- roytri