Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 698
Fuselight Avatar asked Mar 16 '23 00:03

Fuselight


1 Answers

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.
 }
like image 178
Aron Avatar answered Mar 17 '23 18:03

Aron