2010-07-09 2 views
5

У меня есть класс, который использует «System.Net.Sockets.Socket» непосредственно для сети коммуникацию, и в настоящее время я использую следующие два интерфейса разорвать зависимость от класса Цоколь:Как правильно смоделировать высокую задержку при тестировании сервера сокетов C#?

public interface ISocketListener 
    { 
     void Listen(int backlog); 

     ISocket Accept(); 

     void Bind(EndPoint endpoint);    
    } 

public interface ISocket 
    { 
     void Connect (EndPoint ep); 

     Stream CommunicationStream { get; } 

     void Close(); 

     void Close(int timeout); 

     void Shutdown(); 
    } 

В производственной реализации I просто перенаправите все вызовы методов на частный объект Socket. В тестовой среде я использую MemoryStream как коммуникационную «трубу» между сокетами. Поскольку у меня мало опыта в предмете, некоторые вопросы появились у меня в голове при написании тестов: существуют ли какие-либо «формальные» хорошие методы тестирования такого программного обеспечения? При тестировании интеграции, как я могу проверить производительность этого сервера в ситуациях с несколькими соединениями/высокой задержкой (точнее, как имитировать эти ситуации)? Почему существуют асинхронные версии Socket.Accept/Socket.Receive? Могу ли я заменить асинхронные методы обработки своих синхронных версий в отдельных потоках?

ответ

0

Есть ли какие-либо «формальные» хорошие практики при тестировании такого программного обеспечения?

Я могу говорить об этом, но я уверен, что здесь есть какая-то полезная информация о стеке или в дикой природе.

При выполнении интеграционного тестирования, как я могу проверить производительность этого сервера в нескольких соединениях/высокой латентность ситуации (точнее, как имитировать эти ситуации)?

Для простого запуска напишите несколько тестовых и протоколирующих подпрограмм, запустив их в отдельном окне, которое забило сервер с достоверностью запросов ... включая бессмысленные. Запуск log4net на обоих будет также полезен. Представляя некоторое отставание, можно сделать, как уже упоминалось, через прокси-сервер ... поле, которое находится между клиентом и сервером. Клиент указывает на прокси-сервер, а прокси-сервер изменяет данные ... задерживает, меняет порядок пакетов и т. Д .... отправляет серверу обратно и повторяется. Как немного в стороне ... Я бы избегал Thread.Sleep (...). Лучше использовать что-то вроде этого:

lock (timelock) { Monitor.Wait(timelock, TimeoutInMilliseconds); } 

...асинхронные версии Socket.Accept/Socket.Receive? Могу ли я заменить асинхронные методы для , обрабатывая их синхронные версии в отдельных потоков?

У вас есть много вариантов, асинхронные методы, простая старая резьба, threadpool, TPL и т. Д. Лучший выбор - это специфический для приложения.

Вот Asynchronous Server Socket Example из записи MSDN на sockets.

Как повезло бы ... книга O'Reilly: C# 4.0 in a Nutshell имеет отличный набор TCP Server examples, который охватывает как асинхронные, так и поточные методы в блокирующих/неблокирующих проявлениях. Вот один из примеров ...

public class Server 
    { 
    public void Serve(IPAddress address, int port) 
    { 

     TcpListener listener = new TcpListener(address, port); 
     listener.Start(); 
     while (true) 
     { 
     TcpClient c = listener.AcceptTcpClient(); 
     Task.Factory.StartNew(Accept, c); 
     } 
    } 

    void Accept(object clientObject) 
    { 
     using (TcpClient client = (TcpClient)clientObject) 
     { 
     using (NetworkStream n = client.GetStream()) 
     { 
      byte[] data = new byte[5000]; 

      int bytesRead = 0; int chunkSize = 1; 

      while (bytesRead < data.Length && chunkSize > 0) 
      { 
      bytesRead += 
       chunkSize = n.Read /// Read is blocking 
       (data, bytesRead, data.Length - bytesRead); 
      } 

      Array.Reverse(data); 
      n.Write    /// Write is blocking 
      (data, 0, data.Length); 
     } 
     } 
    } 
    } 

Надеюсь, это полезно.

P.S. Получите копию C# 4.0 in a Nutshell ... tis хорошо.

+0

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

+0

. Вы можете, конечно, выполнить свое тестирование в том же окне ... но тогда вы будете использовать один и тот же сетевой стек. Таким образом, ваши результаты будут немного искажены. Это не прерыватель сделки, вы должны просто знать о возможных побочных эффектах ... наслаждаться. – Rusty

1

Я не знаком с объектом сокета. Тем не менее, я провел некоторое исследование по тестированию. Похоже, ты на правильном пути. Написание интерфейсов, которые могут ссылаться либо на фактические объекты, которые будут использоваться в производственных или тестовых объектах, обычно считается хорошей практикой. Этот шаблон известен как «Injection Dependency».

Я не знаю, как работает сокет, но то, что вы можете сделать для тестирования, - создать новый тестовый объект для использования вместо сокета, который вы хотите протестировать. Этот тестовый объект может просто вызвать Thread.Sleep(x), чтобы добавить некоторую симулированную задержку перед возвратом данных.

Редактировать: Я также хотел бы указать, что вам нужно быть очень осторожным, чтобы точно определить, где происходит латентность сети в вашем коде, чтобы при инжекции искусственной задержки вы добавляли ее в то же место в коде, где оно будет происходить в реальном мире.

+0

Вы имеете в виду разделить некоторые двоичные данные на куски и отправить каждый фрагмент с помощью Thread.Sleep interval? Это возможное решение, но я не уверен, правильно ли он имитирует высокую задержку, но я могу попробовать. Как обрабатывать несколько одновременных соединений? как это будет обрабатываться? –

+0

Я хочу сказать, что, поскольку вы написали свой собственный интерфейс, вы должны иметь возможность написать тестовый объект, который имитирует латентность и использовать его в тестовой среде. Я не могу сказать ничего о деталях того, как следует моделировать латентность. –

1

Вы можете имитировать высокую задержку, создав прокси-сервер, чтобы сидеть между ними, тогда вы можете просто добавить задержку при повторной отправке данных.

+0

Вы имеете в виду насмешливый прокси-сервер? Не могли бы вы привести пример? –