Изключение за сокет на Hyper-V машина

Наскоро цялата ни QA среда се премести от VMWare към Hyper-V виртуални машини.

Едно от нашите приложения изпраща UDP пакети към мултикаст облак със скорост от 20K пакета в секунда.

Въпреки че това работи перфектно в средата на VMWare, Hyper-V прави приложението да изведе следното изключение след няколко минути работа:

System.Net.Sockets.SocketException (0x80004005): An invalid argument was supplied
   at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)

Също така успях незабавно да имитирам този проблем, когато дефинирах размера на буфера за изпращане на сокета на 1 000 000 байта.

Как мога да разреша този проблем?

АКТУАЛИЗАЦИЯ 1: Това е запис в регистрационния файл от програмата за преглед на събития, след като се случи изключението:

Faulting application name: Agent.exe, version: 1.0.12.7366, time stamp: 0x51389f69
Faulting module name: KERNELBASE.dll, version: 6.1.7601.18015, time stamp: 0x50b83c8a
Exception code: 0xe0434352
Fault offset: 0x0000c41f
Faulting process id: 0xaf0
Faulting application start time: 0x01ce1b4ce509dc7a
Faulting application path: C:\Users\DevUser\Desktop\QA\Agent.exe
Faulting module path: C:\Windows\syswow64\KERNELBASE.dll
Report Id: d2b45dce-8740-11e2-86f9-00155d022804

АКТУАЛИЗАЦИЯ 2: Размерът на UDP пакета е 100-200 байта.

АКТУАЛИЗАЦИЯ 3: Ето проблемния код:

    m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    m_socket.Ttl = 1;

    if (GetRawParameter("send") != null)
    {
      Log("Starting sender...");

      StartSender();
    }

    ...snip...

private static void StartSender()
{
  m_lastPacketNumber = 0;

  m_socket.Connect(new IPEndPoint(m_ipAddress, m_port));

  if (m_bufferSize > 0)
    m_socket.SetSocketOption(
      SocketOptionLevel.Socket, SocketOptionName.SendBuffer, m_bufferSize);

  byte[] dataPad = null;

  if (m_packetSize > 8)
  {
    dataPad = new byte[m_packetSize - sizeof(long)];

    for (int i = 0; i < dataPad.Length; i++)
    {
      dataPad[i] = 0xFF;
    }
  }

  while (true)
  {
    Log("Sending data...");

    for (int i = 0; i < m_packetsPerSec; i++)
    {
      var data = BitConverter.GetBytes(m_lastPacketNumber.Value);

      if (dataPad != null)
        data = data.Concat(dataPad).ToArray();

      if (m_packetDump != null)
        m_packetDump.Add(m_lastPacketNumber.Value);

      m_socket.Send(data);

      if (m_usePerformanceCounters)
        IncreaseSendCounters(1);

      m_lastPacketNumber++;
    }

    Log(m_lastPacketNumber + " packets sent.");

    Thread.Sleep(1000);
  }
}

АКТУАЛИЗАЦИЯ 4: неуспешното изпращане () изглежда се случва на пакета #14156 или #32485 или #25412 (не първия!), когато се опитам да изпратя 100K пакети в секунда.


person Eran Betzalel    schedule 07.03.2013    source източник
comment
Какъв SocketErrorCode получавате от изключението?   -  person HasaniH    schedule 07.03.2013
comment
ErrorCode = 10022, SocketErrorCode = InvalidArgument.   -  person Eran Betzalel    schedule 07.03.2013
comment
Разбира се, ще получите грешка, когато се опитате да изпратите толкова голям пакет. Най-големият UDP пакет, който можете да изпратите, е около 64K байта. Вижте stackoverflow.com/q/1098897/56778 например.   -  person Jim Mischel    schedule 07.03.2013
comment
Получавате грешка за невалиден аргумент, но не сте си направили труда да разберете какви са аргументите? И това, докато имате метод за незабавна репликация? Помогнете ни да ви помогнем: стартирайте програмиста под дебъгер, за да намерите аргументите! Също така, защо използвате маркера Winsock за този въпрос? Използвате интерфейса на сокети на .NET, а не самия Winsock API. Да, знам, че .NET използва Winsock под капака, но ако това е вашият аргумент, можете също така да очаквате да видите маркера Winsock, използван при голяма част от въпросите {Perl,Python,Ruby,...} тук на ТАКА, също.   -  person Warren Young    schedule 08.03.2013
comment
@WarrenYoung, аргументите са представени по-горе. Това е въпрос на Winsock по простата причина, че 10022 е грешка на Winsock. Изпълнението в режим на отстраняване на грешки няма да помогне, тъй като изключението възниква в етап на ниско ниво на рамката C# winsock.   -  person Eran Betzalel    schedule 08.03.2013
comment
Имам предвид аргументите, които вашият код предаде на System.Net.Sockets.Socket.Send(). Или ако не го извиквате директно, името и аргументите за последната функция на .NET framework, която направите извикате преди изключението да бъде хвърлено.   -  person Warren Young    schedule 09.03.2013
comment
Извиквам го директно и параметърът за изпращане е просто байтов масив от 100 знака.   -  person Eran Betzalel    schedule 09.03.2013
comment
Изглежда, че този въпрос е малко от скалата на високо ниво, затова го публикувах и тук: social.technet.microsoft.com/Forums/en-US/winserverhyperv/.   -  person Eran Betzalel    schedule 10.03.2013
comment
@JimMischel, както беше посочено, опитвам се да изпратя 100 байта данни - не е толкова много :)   -  person Eran Betzalel    schedule 10.03.2013
comment
Значи се обаждаш на Socket.Send(Buffer)? Показването на някакъв код е полезно. В противен случай просто си играеш на глупаци с нас ... а аз имам по-добри неща за вършене.   -  person Jim Mischel    schedule 10.03.2013
comment
Разбира се, @JimMischel, току-що качих кода.   -  person Eran Betzalel    schedule 10.03.2013
comment
Би било поучително да знаете какво е data.Length, когато се обадите на Send. Също така, пълно проследяване на стека, когато е хвърлено изключение. Подозирам обаче, че проблемът е някъде другаде в стека. Опитвам се да разбера защо това работи на VMWare, но не успява на Hyper-V. Може да обмислите изтегляне на източника на Framework от referencesource.microsoft.com/netframework.aspx и да го използвате да влезе в Socket.Send, само за да видиш къде се проваля.   -  person Jim Mischel    schedule 10.03.2013
comment
data.length = 100, изключението възниква при извикването на Win32Api и връща горния код на грешка.   -  person Eran Betzalel    schedule 11.03.2013
comment
Възможно ли е вашият буфер да се променя по време на изпращането? Може би има друга работеща нишка, която не е показана?   -  person Paul Farry    schedule 12.03.2013
comment
Моето тестово приложение използва само една нишка - тук няма проблем.   -  person Eran Betzalel    schedule 12.03.2013
comment
Това случва ли се, когато се опитате да ги изпратите до локалната обратна връзка или едноадресен адрес?   -  person yasth    schedule 27.03.2013
comment
Изпращам пакетите през комутатора за виртуална мрежа HyperV.   -  person Eran Betzalel    schedule 28.03.2013
comment
Може да се сблъскате с проблеми с hyper-v и VMQ, което изглежда се случва донякъде на случаен принцип при натоварване. Наскоро реших подобен проблем, като деактивирах VMQ. Вижте alexappleton.net/post/77116755157/   -  person AVee    schedule 17.09.2014


Отговори (1)


Можете ли да "навиете" пакетите, така че да изпращате много по-малко пакети с по-голям размер...и след това да ги разгънете от другата страна? 20k пакета/секунда са много sendto.

person raetza    schedule 26.03.2013
comment
Не мога да забавя или буферирам данните, преди да ги изпратя. Действителното изискване е 100K, което всъщност работи с помощта на VMWare машини. - person Eran Betzalel; 28.03.2013