Смешивание синхронных и асинхронных вызовов сокетов - PullRequest
1 голос
/ 23 октября 2010

Считается ли плохой практикой объединять синхронные и асинхронные вызовы сокетов на одном сервере? Например (изменено из MSDN):

// Initalize everything up here

while (true) {
     // Set the event to nonsignaled state.
     allDone.Reset();  //allDone is a manual reset event

     // Start an asynchronous socket to listen for connections.
     Console.WriteLine("Waiting for a connection...");
     listener.BeginAccept( 
     new AsyncCallback(AcceptCallback), listener);

      // Wait until a connection is made before continuing.
      allDone.WaitOne();
}

public static void AcceptCallback(IAsyncResult ar) {
    // Signal the main thread to continue.
    allDone.Set();

    // Handle the newly connected socket here, in my case have it
    // start receiving data asynchronously
}

В этом случае, поскольку вы ждете, пока каждое соединение не будет установлено, прежде чем прослушивать следующее соединение, кажется, что это в значительной степени блокирующий вызов. Учитывая, что это должно быть немного быстрее, потому что первоначальная обработка клиента будет выполняться в другом потоке, но теоретически это должно быть относительно небольшая нагрузка.

Учитывая это, будет ли считаться плохой практикой делать что-то вроде:

while (true) {
     // Start listening for new socket connections
     Socket client = listener.Accept(); // Blocking call


    // Handle the newly connected socket here, in my case have it
    // start receiving data asynchronously
}

как мне кажется, этот код намного проще, чем приведенный выше код, и, если я не ошибаюсь, производительность должна быть относительно близка к приведенному выше.

1 Ответ

3 голосов
/ 23 октября 2010

Глядя на ваши два примера, я вижу очень небольшую разницу (если вообще есть) в том, что происходит. Рискну предположить, что ваша вторая форма (прямо для синхронного вызова) лучше, потому что она гораздо менее сложна и идентична по поведению. Если бы вы могли посмотреть на источник для Accept, в какой-то момент (возможно, в ОС) он будет работать почти так же, как ваш более подробный код.

Однако ...

Очень быстрый мод для вашего старого кода устраняет все блокировки и позволяет всему происходить асинхронно:

void Accept()
{
    Console.WriteLine("Waiting for a connection...");
    listener.BeginAccept(AcceptCallback, listener);
}
public static void AcceptCallback(IAsyncResult ar) {
            var listener = (Socket)ar.AsyncState;
            //Always call End async method or there will be a memory leak. (HRM)                
            listener.EndAccept(ar); 
    Accept();

    //bla
}

мммм ... намного лучше.

...