Socket.SendAsync не отправляет заказ в Mono / Linux - PullRequest
3 голосов
/ 31 января 2011

Существует однопоточный сервер, использующий .NET Socket с протоколом TCP, и Socket.Pool(), Socket.Select(), Socket.Receive().

Для отправки я использовал:

public void SendPacket(int clientid, byte[] packet)
{
    clients[clientid].socket.Send(packet);
}

Но это было очень медленно при отправке большого количества данных одному клиенту (остановка всего основного потока), поэтому я заменил его следующим:

public void SendPacket(int clientid, byte[] packet)
{
    using (SocketAsyncEventArgs e = new SocketAsyncEventArgs())
    {
        e.SetBuffer(packet, 0, packet.Length);
        clients[clientid].socket.SendAsync(e);
    }
}

Он отлично работает в Windows с .NET (я не знаю, идеально ли это), но в Linux с Mono пакеты либо отбрасываются, либо переупорядочиваются (не знаю). Возврат к медленной версии с Socket.Send () работает в Linux. Источник для всего сервера .

Как написать неблокирующую функцию SendPacket (), которая работает в Linux?

Ответы [ 3 ]

1 голос
/ 31 января 2011

Я собираюсь предположить, что это связано с вашим оператором using и вашим вызовом SendAsync.Возможно, e выпадает из области видимости и удаляется, пока SendAsync все еще обрабатывает буфер.Но тогда это может вызвать исключение.Я действительно просто догадываюсь.Попробуйте удалить оператор using и посмотрите, что произойдет.

0 голосов
/ 11 декабря 2013

У меня такая же проблема;Linux и Windows реагируют не так, как SendAsync.Иногда linux усекает данные, но есть обходной путь.Прежде всего вам нужно использовать очередь.Каждый раз, когда вы используете SendAsync, вы должны проверять обратный вызов.Если e.Offset + e.BytesTransferred

Я не знаю, почему mono-linux считает, что он завершен до отправки всех данных, и это странно, но я уверен, что он это делает.

0 голосов
/ 31 января 2011

Я бы сказал, не злоупотребляя асинхронным методом.Вы нигде не найдете документацию о том, что это на самом деле вынуждено поддерживать порядок.он ставит iem в очередь для планировщика, который распределяется по потокам, и, игнорируя тот факт, что oder не поддерживается для каждой документации, вы открываете себя для деталей реализации.

Лучше всего:

  • Иметь очередь на сокет.
  • Когда вы пишете dasta в эту очередь, а рабочий поток отсутствует, запускайте рабочий элемент (ThreadPool) для обработки потока.

Таким образом, у вас есть отдельные отдельные очереди, которые поддерживают порядок.Только один поток будет обрабатывать одну очередь / сокет.

...