Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Existing c# socket server library using SocketAsyncEventArgs?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 wildbunny   Members   -  Reputation: 550

Like
0Likes
Like

Posted 22 July 2012 - 11:30 AM

Hi guys,

I've just discovered my socket server isn't fit for purpose, so now I need a new one based on SocketAsyncEventArgs.

Does anyone know of any pre-existing library designed around SocketAsyncEventArgs? I really don't want to reinvent the wheel again :|

Cheers, Paul.

Sponsor:

#2 Drew_Benton   Crossbones+   -  Reputation: 1727

Like
0Likes
Like

Posted 22 July 2012 - 04:08 PM

Based on your other thread, I'd strongly urge you to slow down and actually work out you current problem rather than rushing to potentially solve the wrong one.

The alternate asynchronous pattern SocketAsyncEventArgs provides is a very advanced model that caters to very specific needs. When they (Microsoft) say the model is for "specialized high-performance socket applications", they mean a very specific thing, not a general thing that you are thinking about. The model is meant to help developers control almost all aspects of resource costs for servicing 1000s, 10s of thousands, to even 100s of thousands+ worth of concurrent connections or an extremely high network I/O throughput. If you do not properly implement all aspects of this model, your solution essentially degrades into the same model provided by the Being/EndXXX API, just more complicated and bug filled.

There's more to using the model than just the networking aspect. The rest of your code is vital in determining whether or not the networking can even scale to its max potential on the hardware you provide. The most basic and specific example is "global shared state". The more "global shared state" you have, the less efficient async models become due to locking. While there are certain ways around this, it is a very advanced topic.

What's the point about talking about all this? The point of using this model is that you control all aspects of it. You would be hard pressed to find a generic socket server library that utilized SocketAsyncEventArgs because of how specialized the solution is. Whatever you might find, you certainly wouldn't want to use without understanding the core concepts first because typically speaking, you will be finding unsupported code that will have tons of bugs in it that will negatively affect your application down the road. If you needed a library that did all of this for you, then use the Begin/EndXXX API!

The bigger issue at hand though is that if you are having issues with the Begin/EndXXX API, the XXXAsync API functions will not magically solve your problems, especially if you do not understand what the problems are in the first place. That is why you need to try to figure out the real problem first. If there's one thing I've learned over many years of working with networked applications is that there's nothing worse than solving the wrong problem using an even more complicated solution because you did not take the time to understand the inherent flaws in your code.

You should really post code in your other thread if you want to get more help as right now, all people can do is guess. Programming and guessing do not go together, especially if you hope to get a problem solved.

"But I, being poor, have only my dreams. I have spread my dreams under your feet; tread softly, because you tread on my dreams." - William Butler Yeats

#3 hplus0603   Moderators   -  Reputation: 5693

Like
0Likes
Like

Posted 23 July 2012 - 02:42 AM

BeginSend() and friends should have no problem serving 10 clients over TCP with next to no lag introduced by the network layer.

Looking at the other thread you posted, I'd suspect the problem lies elsewhere. For example:
How big is your available send bandwidth on the server?
How do you measure ping?
How are you sure that NoDelay is turned on?
Is there any locking in your async callbacks?

Start with a network capture using something like Wireshark, and study it in detail. Also, use a variety of profilers to study the server and client behavior.

Edited by hplus0603, 23 July 2012 - 02:44 AM.

enum Bool { True, False, FileNotFound };

#4 wildbunny   Members   -  Reputation: 550

Like
0Likes
Like

Posted 23 July 2012 - 03:37 AM

My OnAccept function looked like this:

[source lang="csharp"]OnConnect();while (state.m_ClientSocket.Connected){ // Set the event to nonsignaled state. state.m_readDone.Reset(); client.BeginReceive(state.m_buffer, 0, StateObject.kBufferSize, 0, new AsyncCallback(ReadCallback), state); // Wait until data is ready to be read before continuing, or timeout and check for disconnection state.m_readDone.WaitOne(m_milliSecondsSocketTimeout);}OnDisconnect();[/source]

This would run in a separate thread for each client (since it was called from BeginAccept). At the end of the function ReadCallback, I would set the m_readDone flag so the process could continue. Then I realised there wasn't really any point to using BeginReceive() here because it would create yet another new thread for every client read.

I changed to this:

[source lang="csharp"]OnConnect();while (state.m_ClientSocket.Connected){ // this is the client message loop int bytesRead = client.Receive(state.m_buffer); ReadCallback(state, bytesRead);}OnDisconnect();[/source]

And my lag disappeared. Now, unless I am horribly mistaken this can only mean the horrible lag was caused simply by the creation of a new thread for every receive and also the thread wrangling I was doing.

Since I would like to have 200 or more clients connected on one server, I've begun to fear this Begin() thread creation methodology. This is why I've been exploring SocketAsyncEventArgs.

Cheers, Paul.

#5 wildbunny   Members   -  Reputation: 550

Like
0Likes
Like

Posted 23 July 2012 - 08:36 AM

Upon re-examining the situation, doing some more research and in respect of people's advice on this thread I've decided to keep my original socket server but modify it a bit.

I think my problem was I was starving the IO completion thread pool by creating a never ending loop inside the BeginAccept() callback. I've recently found this article by microsoft which demonstrates a number of different ways to approach a socket server in .net, its a highly valuable read: http://msdn.microsoft.com/en-us/magazine/cc300760.aspx

Now what I'm doing is to keep using the Begin() methodology but to never keep any callback threads running. This seems to be working well and my lag is gone, and the changes to my original code were minimal.

Thanks for all your help!

Cheers, Paul.

#6 hplus0603   Moderators   -  Reputation: 5693

Like
0Likes
Like

Posted 23 July 2012 - 10:34 AM

the creation of a new thread for every receive


Some people on this board would probably think "well, Duh!" when reading that :-)

I suggest that you read the FAQ for this forum. It has some good suggestions, such as "don't create a thread per client."

When it comes to async I/O in C#, you want to use the completion callback function to know that things have completed, and you don't want to create any threads at all on your own. The main thread should be sufficient for your "control" code, and the OS/framework will take care of creating/re-using threads for the asynchronous sends/receives.

Because the callbacks are asynchronous, you need to use some kind of synchronization hand-off between the callback and the actual processing code. That can easily be done with a lock() block or similar, though.



enum Bool { True, False, FileNotFound };

#7 wildbunny   Members   -  Reputation: 550

Like
0Likes
Like

Posted 23 July 2012 - 02:00 PM

I guess it may seem obvious, but it was kind of hidden from view for the simple reason that the thread management is not under your control with Begin() methodology; the threads are dished out by the socket library and its up to you to relinquish control of them as quickly as possible, which is what I hadn't fully grasped until just recently.

So I would have been following the FAQ and still come across this problem. Its only when you sit down and really research and think about what's going on that it becomes obvious what's really happening :)

Cheers, Paul.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS