Сокет C#. BeginReceive/EndReceive

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

Независимость Контекста

Декларативные Программы независимы от контекста . Поскольку они только объявляют, какова конечная цель, но не посредник ступает для достижения той цели, та же программа может использоваться в различных контекстах. Это трудно относится обязательные программы , потому что они часто зависят от контекста (например, скрытое состояние).

Берут yacc в качестве примера. Это - парсер-генератор иначе. компилятор компилятора, внешний декларативный DSL для описания грамматики языка, так, чтобы синтаксический анализатор для того языка мог автоматически быть сгенерирован из описания. Из-за его независимости контекста можно сделать много разных вещей с такой грамматикой:

  • Генерируют синтаксический анализатор C для той грамматики (исходный вариант использования для yacc)
  • Генерируют синтаксический анализатор C++ для той грамматики
  • , Генерируют синтаксический анализатор Java для той грамматики (использующий Jay)
  • , Генерируют синтаксический анализатор C# для той грамматики (использующий GPPG)
  • , Генерируют синтаксический анализатор Ruby для той грамматики (использующий Racc)
  • , Генерируют древовидную визуализацию для той грамматики (использующий GraphViz)
  • , просто делают некоторую симпатичную печать, форматирующую воображение и подсветку синтаксиса самого yacc исходного файла и включают его в Ваш Справочник как синтаксическая спецификация Вашего языка

И намного больше …

Оптимизация

, поскольку Вы не предписываете компьютер, который ступает для взятия и в том, какой порядок, это может перестроить программу намного более свободно, возможно, даже, выполняют некоторые задачи параллельно. Хорошим примером является планировщик запроса и оптимизатор запросов для базы данных SQL. Большинство баз данных SQL позволяет Вам отображать запрос, что они на самом деле выполнение по сравнению с запросом, который Вы попросили их выполнять. Часто, те запросы взгляд ничто друг как друг. Планировщик запроса берет вещи во внимание, что Вы даже не мечтали бы о: вращательная задержка подложки диска, например, или того, что некоторое совершенно другое приложение для совершенно другого пользователя просто выполнило подобный запрос и таблицу, к которой Вы присоединяетесь и что Вы упорно работали так, чтобы не загружаться, уже находится в памяти так или иначе.

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

9
задан Islam Saad Darwish 10 July 2014 в 22:33
поделиться

4 ответа

Если 1300 файлов компилируются ТАК долго, значит, вы включаете слишком много файлов заголовков, которые не нужны. Я предполагаю, что люди вырезали и вставили кучу файлов заголовков в файл CPP, не задумываясь, какие заголовки им действительно нужны, чтобы множество из них было включено, когда им не должно быть. Я также предполагаю, что вы не объявляете классы там, где должны быть.

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

5 Версия

С поддержкой асинхронного режима в C # 5 появилась новая опция. Это использует компилятор для генерации продолжений вручную (отдельные методы обратного вызова) и замыканий (состояния) из встроенного кода. Однако есть две вещи, которые нужно обойти:

  1. Хотя System.Net.Sockets.Socket имеет различные методы … Async , они предназначены для асинхронного шаблона на основе событий, а не для ] Шаблон на основе задачи , который использует await C # 5. Решение: используйте TaskFactory.FromAsync , чтобы получить одну Task из пары Begin… End… .

  2. TaskFactory.FromAsync поддерживает только передачу до трех дополнительных аргументов (в дополнение к обратному вызову и состоянию) в Begin… . Решение: лямбда, принимающая ноль дополнительных аргументов, имеет правильную сигнатуру, и C # даст нам правильное закрытие для передачи аргументов.

Следовательно (и более полно реализовано с Message , являющимся другим типом, который обрабатывает преобразование из начальная отправка длины, закодированной в некотором фиксированном количестве байтов, затем байтов содержимого в длину для буфера содержимого):

private async Task<Message> ReceiveAMessage() {
  var prefix = new byte[Message.PrefixLength];

  var revcLen = await Task.Factory.FromAsync(
                         (cb, s) => clientSocket.BeginReceive(prefix, 0, prefix.Length, SocketFlags.None, cb, s),
                         ias => clientSocket.EndReceive(ias),
                         null);
  if (revcLen != prefix.Length) { throw new ApplicationException("Failed to receive prefix"); }

  int contentLength = Message.GetLengthFromPrefix(prefix);
  var content = new byte[contentLength];

  revcLen = await Task.Factory.FromAsync(
                         (cb, s) => clientSocket.BeginReceive(content, 0, content.Length, SocketFlags.None, cb, s),
                         ias => clientSocket.EndReceive(ias),
                         null);
  if (revcLen != content.Length) { throw new ApplicationException("Failed to receive content"); }

  return new Message(content);
}
20
ответ дан 4 December 2019 в 07:47
поделиться

Возможно, вы хотите связать ваши обратные вызовы в цепочку:

псевдокод:



// read the first 2 bytes as message length
BeginReceive(msg,0,2,-,-,new AsyncCallback(LengthReceived),-)

LengthReceived(ar) {
  StateObject so = (StateObject) ar.AsyncState;
  Socket s = so.workSocket;
  int read = s.EndReceive(ar);
  msg_length = GetLengthFromBytes(so.buffer);
  BeginReceive(so.buffer,0,msg_length,-,-,new AsyncCallback(DataReceived),-)
}

DataReceived(ar) {
  StateObject so = (StateObject) ar.AsyncState;
  Socket s = so.workSocket;
  int read = s.EndReceive(ar);
  ProcessMessage(so.buffer);
  BeginReceive(so.buffer,0,2,-,-,new AsyncCallback(LengthReceived),-)
}

см.: http://msdn.microsoft.com/en-us /library/system.asynccallback.aspx для правильных примеров

6
ответ дан 4 December 2019 в 07:47
поделиться

Обычно методы BeginXXX указывают на асинхронную операцию, и вы, кажется, хотите сделать это синхронно.

Если вам действительно нужен синхронный клиент / сервер, возможно, это поможет http://sharpoverride.blogspot.com/2009/04/another-tcpip-server-client-well-it.html

1
ответ дан 4 December 2019 в 07:47
поделиться

It will help if you describe the structure of the message you are sending.

As long as you have only one BeginReceive() outstanding, it will complete and give you the next available bytes of data on the wire. If you have more than one outstanding at the same time, then all bets are off, because .net does not guarantee that the completion will be in any given order.

1
ответ дан 4 December 2019 в 07:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: