Сокет .NET Remoting не умрет даже после того, как процесс

Пожалуйста, рассмотрите этот довольно простой сценарий. У меня есть два консольных приложения .NET 4.0/С#. Назовем их имена «Launcher» и «SocketApp».

Launcher не делает ничего, кроме запуска SocketApp при определенных обстоятельствах. Это делается с помощью метода Process.Start(). SocketApp работает какое-то время, и через некоторое время его цикл Main() завершается, и процесс умирает. И процесс остается мертвым, пока Launcher не запустит его снова. (Ни при каких условиях не будет запущено несколько экземпляров SocketApp). И так цикл идет. Это работает нормально в течение нескольких дней.

Но иногда SocketApp не запускается. Он выдает исключение, когда канал удаленного взаимодействия пытается прослушивать сокет. Исключение создается глубоко во внутреннем коде Remoting, точнее, при вызове Bind(). Причина сбоя вызова привязки заключается в том, что сокет каким-то образом никогда не освобождался при ПРЕДЫДУЩЕМ успешном запуске SocketApp. Я знаю, что это так, потому что если я гарантирую, что SocketApp закрыт, и я делаю netstat -n, я вижу, что порт, к которому я хочу Bind(), привязан. Он находится в постоянном состоянии CLOSE_WAIT. И он просто остается в этом состоянии CLOSE_WAIT навсегда.

Единственный способ заставить Windows освободить этот сокет — это (и это становится странным) закрыть приложение Launcher. С чего бы это? Launcher работает в своем собственном процессе и вообще не использует сокеты. Его единственная цель - запустить SocketApp. Так почему же закрытие Launcher освобождает сокет, который использует только SocketApp? Может быть, это потому, что я не вызываю Dispose() для объекта Process из Launcher? Этот сбой появляется так редко, что требуется несколько дней, чтобы определить, эффективно ли какое-либо конкретное исправление. Что-нибудь еще, на что я должен смотреть?

Декстер


person Dexter Morgan    schedule 16.03.2011    source источник
comment
Я бы поспорил на чашку с арахисовым маслом King Sized Reese's, что проблема в том, что вы не вызываете Dispose () из программы запуска, как вы просили, но я недостаточно уверен в этом, чтобы опубликовать это как ответ. Мне это наиболее понятно, учитывая, как работает сборка мусора.   -  person David    schedule 16.03.2011
comment
Я добавил вызов Dispose(). Через несколько дней я узнаю, эффективно ли это. В ОТНОШЕНИИ: Я не слишком хорошо знаком с этим сайтом. В чем разница между комментарием и ответом?   -  person Dexter Morgan    schedule 16.03.2011
comment
Комментарии не добавляются к репутации. Комментарии предназначены для побочного обсуждения вопросов и ответов. Иногда, если у людей нет окончательного ответа, они публикуют его в виде комментария.   -  person Mike Atlas    schedule 16.03.2011
comment
Кроме того, вместо добавления вызова Dispose() используйте предложение using(){}, которое сделает это за вас. msdn.microsoft.com/en-us/library/yh598w02.aspx   -  person Mike Atlas    schedule 16.03.2011


Ответы (1)


На самом деле выпуск порта в этот момент находится в руках операционной системы. Порт будет использоваться в течение 4 минут по умолчанию в Windows. Вот ссылка на unix.

person Mike Atlas    schedule 16.03.2011
comment
Да, разумный человек так бы и подумал. Я видел ссылки на этот 4-минутный тайм-аут по всему Интернету, но, к сожалению, это не то, что происходит. Он остается в состоянии CLOSE_WAIT навсегда... пока я не закрою LauncherApp. :( - person Dexter Morgan; 16.03.2011
comment
Похоже, вы пропускаете вызовы Dispose. Оберните использование сокета в операторе using msdn.microsoft.com/en-us/ библиотека/yh598w02.aspx - person Mike Atlas; 16.03.2011