Windows 8 -.NET TCP AcceptAsync callback не запускается (заблокирован Console.ReadLine())
У меня возникла проблема, связанная с Windows 8 и VS2012.
У меня есть сервер и клиент сокета TCP, и я тестирую локальную сеть. С sysinternals TCPView я вижу, что пакеты отправляются из TCP-клиента и поступают на TCP-сервер (я вижу, что счетчики пакетов увеличиваются).
Однако, похоже, что данные не попадают в стек приложения?
Сама же сборка работает без проблем в Windows 7.
У меня отключен брандмауэр Windows 8 и запускается оба процесса с повышенными разрешениями для пользователей домена с отключенным UAC.
Когда я подключаю клиент к внешнему серверу (работает на отдельной машине), все работает нормально.
Есть ли что-то еще в Windows 8, которые могут запрещать передачу данных TCP между локальными процессами?
Спасибо,
ИЗМЕНИТЬ
Чтобы убедиться, что ничто в моем серверном приложении не вызывает этой проблемы, я создал быстрый сервер TCP в консольном приложении со следующим кодом для конструктора сокетов:
listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
и прослушивать один и тот же локальный IP-порт в качестве моего серверного приложения.
Я испытываю ту же проблему, я могу telnet к порту, но listenerSocket.AcceptAsync никогда не попадал.
РЕДАКТИРОВАТЬ 2
При последующем тестировании он обнаруживает, что моя проблема имеет какое-то отношение к использованию вызовов сокета Async, то есть если я использую синхронные вызовы типа socket.Accept(), тестовое приложение работает нормально. Однако, когда я использую вызовы сокета Async, то есть socket.AcceptAsync(), я испытываю упомянутые проблемы. До сих пор я не мог найти упоминания о различиях между win7 и 8 в отношении вызовов асинхронного сокета.
Здесь мое приложение быстрого примера, которое показывает, что асинхронный обратный вызов никогда не запускается. Этот фрагмент отлично работает в Windows 7, но не работает в Windows 8 (попробуйте выполнить telnet до 127.0.0.1: 7000).
class Program
{
private static SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs();
static void Main(string[] args)
{
var listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenerSocket.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 7000));
listenerSocket.Listen(100);
socketAsyncEventArgs.Completed += AcceptEventArg_Completed;
listenerSocket.AcceptAsync(socketAsyncEventArgs);
Console.ReadLine();
}
private static void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
{
Console.WriteLine("AcceptEventArg_Completed");
}
}
РЕДАКТИРОВАТЬ 3
Я обнаружил, что еще 2 человека сообщали об одной и той же проблеме в Microsoft Connect:
https://connect.microsoft.com/VisualStudio/feedback/details/759913/socketasynceventargs-completed-doesnt-fire-in-net-framework-4-5
а также
http://connect.microsoft.com/VisualStudio/feedback/details/747218/saea-not-working-in-net-4-5-rp
В то время как второй интересен, поскольку, как представляется, в вызове Console.ReadLine() возникает ошибка Windows, и это вызывает проблему и блокирует обратный вызов async. Если я заменил Console.ReadLine() в своем фрагменте с помощью:
while (true)
{
System.Threading.Thread.Sleep(10);
}
все работает нормально.
Ответы
Ответ 1
См. следующее: GetQueuedCompletionStatus не может деактивировать IO из IOCP, если поток, который изначально выдал IO, блокирует ReadFile в окнах 8
Это ошибка в Windows 8 и 2012 и затрагивает все программы, которые использовали AcceptEx и ReadFile. На данный момент известны только эти две функции.
Ответ 2
Я встречаю то же самое, когда разрабатывал серверные и клиентские приложения Tcp с помощью SocketAsyncEventArgs
Я предлагаю вам попробовать это первым.
-
открыть брандмауэр Windows с расширенной безопасностью
проверьте входящие/исходящие правила, чтобы узнать, заблокировано ли ваше приложение.
-
откройте AssemblyInfo.cs и измените
[сборка: Guid ( "06985fe3-80eb-48b4-940a-fd926e2f2053" )]
для любого другого значения guid.
Изменив это, окна подумают, что это новое приложение, и если есть какие-либо ограничения для старого приложения, оно не будет на новом.
Ответ 3
Звучит как эта ошибка Windows, связанная с обработкой IOCP (возможно, только AcceptEx) в Windows 8, в то время как в этом же потоке выполняется другой блокирующий ввод-вывод:
http://social.technet.microsoft.com/Forums/en-GB/winserver8gen/thread/5764cd0f-fda1-4cfa-ae35-808210bae77e
Итак, соединение сокета принято, но ваше приложение никогда не получает уведомления об этом.
Возможно, Windows 8 делает некоторые странные, слабые сломанные, voodoo для преобразования синхронного ввода-вывода, такого как Console.Read in async внутренне.
Вы можете просто переместить код сервера в другой поток, другие способы обхода, чтобы попытаться выполнить синхронизацию Accept или изменить обработку консоли как асинхронную (я не могу попробовать, поскольку у меня нет Windows 8).