Nodebay
Nodebay

Reputation: 554

C# Concurrent and Async Socket Connections

I'm working on a simple socket server that is supposed to take in multiple connections and hand them off to a "connection" class by means of EndAccept() The problem is that after accepting a connection, the code doesn't accept anything further until the connection ends.

I create the socket in Main() like so, then I pass the socket to ServerEnvironment (static class) via Initialize().

MainSocket.Bind(new IPEndPoint(IPAddress.Parse(Addr), Port));
MainSocket.Listen(10);

ServerEnvironment.Initialize(MainSocket);

while (true)
{
    Console.ReadLine();
    Console.WriteLine(">>");
}

Once MainSocket has been passed, ServerEnvironment takes over from there.

static Socket MainSocket;

public static void Initialize(Socket _MainSocket)
{
    MainSocket = _MainSocket;

    AcceptGameConnection = new AsyncCallback(AddConnection);
    MainSocket.BeginAccept(AcceptGameConnection, null);
}

public static void AddConnection(IAsyncResult Result)
{
    Socket UserSocket = MainSocket.EndAccept(Result);
    ConnectionCount++;

    // Removed the stuff that happens to UserSocket because the same
    // symptoms occur regardless of their presence.

    MainSocket.BeginAccept(AcceptGameConnection, null);
 }

As I search about this question, I come to find that multithreading could be a necessity for my purposes. However, when I use Console.WriteLine(Thread.CurrentThread.ManagedThreadId); in both Initialize(); and AddConnection();, two different thread IDs appear, so I assume that multithreading is already a capability and I don't need to manually create a thread. That wouldn't explain my issue, though.

Is multithreading necessary for me to be able to have concurrent and asynchronous socket connectivity?

EDIT: Binding error..was binding to my LAN address which caused some problems.

Upvotes: 4

Views: 1258

Answers (2)

Aron
Aron

Reputation: 15772

This is how you want to do this if you are using .net 4.0 or less

public static void Initialize(Socket _MainSocket)
{
    MainSocket = _MainSocket;

    AcceptGameConnection = new AsyncCallback(AddConnection);
    MainSocket.BeginAccept(result => {
        var userSocket = MainSocket.EndAccept(result);
        var thread = new Thread(AddConnection);
        thread.Start(userSocket);
        Initialize(MainSocket);
    }, null);
 }

 public static void AddConnection(IAsyncResult Result)
 {
     MainSocket.BeginAccept(AcceptGameConnection, null);
 }

 private static void AddConnection(Socket userSocket)
 {
     // Removed the stuff that happens to UserSocket because the same
     // symptoms occur regardless of their presence.
 }

But this is how you can do it in .net 4.5 or above.

public static void Initialize(Socket mainSocket)
{           
    while(true)
    {
        var userSocket = await Task.Factory.FromAsync(
                                mainSocket.BeginAccept,
                                mainSocket.EndAccept);
        ThreadPool.QueueUserWorkItem(_ => AddConnection(userSocket));
    }
 }

 private static void AddConnection(Socket userSocket)
 {
     // Removed the stuff that happens to UserSocket because the same
     // symptoms occur regardless of their presence.
 }

Upvotes: 4

usr
usr

Reputation: 171236

The problem is that after accepting a connection, the code doesn't accept anything further until the connection ends.

This happens because the next BeginAccept call is delayed by something, probably by code not shown here. Accepting asynchronously is almost always pointless. Don't copy blindly from the terrible Microsoft tutorials. Your accept loop should be:

while (true) {
 var socket = Accept();
 StartProcessing(socket); //Cannot block!
}

That's all.

You can implement StartProcessing using Task and await. This makes asynchronous socket IO rather simple to do. Alternatively, start a new task/thread per connection that you receive.

simple socket server

Such a thing does not exist. You better leave sockets alone and use a ready made higher level protocol such as WCF or HTTP.

Upvotes: 3

Related Questions