2009-09-25 12 views
5

Mam więc aplikację z dostępnym API .NET. Ich biblioteka API komunikuje się z główną aplikacją poprzez .NET zdalne wywoływanie połączeń. Aby korzystać z interfejsu API, aplikacja musi być już uruchomiona.Jak mogę sprawdzić, czy inna aplikacja zarejestrowała kanał Remoting IPC?

Mam więc instancję, w której muszę programowo uruchomić aplikację, a następnie utworzyć instancję jednego z obiektów API, który próbuje otworzyć kanał zdalny IPC do głównej aplikacji. Problem polega na tym, że po uruchomieniu procesu jest kilka sekund pomiędzy uruchomieniem i kiedy aplikacja rejestruje kanał. Jeśli próbuję utworzyć instancję obiektu API przed zarejestrowaniem kanału, zostanie usunięty.

Nie pomaga mi to, że bardzo niewiele wiem o zdalnym .NET.

Jak określić na podstawie MOJEJ aplikacji, która korzysta z interfejsu API, jeśli ich aplikacja zarejestrowała kanał komunikacji, więc wiem, że można utworzyć instancję obiektu API?

+0

Jon Skeet! Musisz znać odpowiedź! = [ – snicker

Odpowiedz

2

Spróbuj tego:

using System.Net.NetworkInformation; 
using System.Net; 
private static bool IsPortAvailable(int port) 
{ 
     IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties(); 
     IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners(); 
     if (activeListeners.Any(conn => conn.Port == port)) 
     { 
      return true; 
     } 
     return false; 
} 

Pass w porcie i powinieneś dostać wartość wskazującą, czy istnieje słuchacz na tym port.Hope to pomaga

+1

Problem jest ... nie jest to port. To zdalne IPC, więc istnieją "nazwy portów", ale nie rzeczywiste porty. – snicker

+0

Jeśli programujesz tworzenie procesu, który nasłuchuje połączeń, to musi nasłuchiwać na jakimś porcie. Ten przykład MSDN ma serwer nasłuchujący wywołań IPC na porcie 9090: http://msdn.microsoft.com/en-us/library/system.runtime.remoting.channels.ipc.ipcchannel.aspx Jeśli nie t znać port, spróbuj uruchomić netstat z linii komend, powinieneś być w stanie zobaczyć, które porty są w użyciu –

+0

Ach, to wydaje się mieć sens. Port zmienia się jednak losowo. Wszelkie sugestie na ten temat? – snicker

0

Wystarczy wyjść z pudełka dla chwila, czy myślałeś o użyciu WCF z MSMQ? Nie jestem pewien, czy w pełni rozumiem, że jesteś architektem, ale wygląda na to, że klient API musi uruchomić inny proces obsługujący interfejs API. Może występować problem z synchronizacją czasu między uruchomieniem hosta API a próbą nawiązania połączenia przez klienta. Microsoft niedawno wycofał .NET Remoting (jak również wszystkie inne wcześniejsze technologie komunikacyjne, takie jak usługi sieciowe ASMX), jako dziedzictwo i bardzo zaleca, aby programiści przenieśli się na platformę WCF.

Jeśli używasz WCF z MSMQ, nie powinieneś mieć problemu z synchronizacją. Twoja aplikacja kliencka może usuwać wiadomości w trwałej kolejce, niezależnie od tego, czy host API jest uruchomiony, czy nie. Host API można uruchomić w dowolnym momencie, a on odbierze i przetworzy wszystkie wiadomości oczekujące w kolejce. Nawet jeśli nadal masz aplikację klienta uruchamiającą hosta interfejsu API, problem z taktowaniem nie będzie już problemem, ponieważ używasz kolejkowania do przesyłania wiadomości, a nie .NET Remoting. WCF zapewnia ładną, wygodną i łatwą w użyciu owijkę wokół MSMQ, więc bariera wejścia jest stosunkowo niska.

Inną piękną rzeczą związaną z korzystaniem z WCF przez .NET Remoting jest możliwość przeniesienia hosta API na inny serwer fizyczny bez konieczności zmiany aplikacji klienckich. Możesz nawet przejść na inną platformę kolejkowania, jeśli sobie tego życzysz (np. RabbitMQ na AMQP), bez zmieniania aplikacji hosta klienta lub interfejsu API. WCF obsługuje całą tę interakcję za ciebie, zapewniając znacznie czystsze oddzielanie i bardziej niezawodną komunikację między aplikacją klienta a hostem API.

Jeśli przejście do WCF nie jest opcją, powinieneś być w stanie jawnie ustawić port za pomocą .NET Remoting. Nie jestem pewien, w jaki sposób konfigurowania hosta API, ale URL dla danego odludziu obiektu jest zazwyczaj w formie:

tcp://<hostname>[:<port>]/<object> 

Jeśli dodać do portu, to powinieneś być w stanie wykorzystać rozwiązanie Abhijeet do określić, czy port jest otwarty, czy nie. Nie uzyskasz luźnego sprzężenia i niezawodnych korzyści komunikacyjnych WCF, ale na pewno będzie to mniej pracy. ;)

+0

WCF nie jest opcją. Nie kontroluję źródła serwera. Istnieje zamknięta aplikacja źródłowa napisana w języku niezarządzanym (prawdopodobnie C++) i API dostarczonym jako biblioteka .NET. Biblioteka tworzy obiekty zdalne. Muszę używać zdalnego przekazywania, chociaż wiem, że jest przestarzałe i jest do bani. – snicker

0

Czy rozważałeś zawijanie próby utworzenia obiektu API w blok try-catch? Następnie możesz przeanalizować wyjątek i sprawdzić, czy nie został on wysłuchany przez serwer. A jeśli tak, możesz po prostu poczekać i spróbować ponownie.

Ma sens?

+0

Tak, ale niestety interfejs API o zamkniętym kodzie źródłowym jest napisany nieprawidłowo i ustawia pewne zmienne statyczne, które uniemożliwiają jego ponowne utworzenie w tym samym środowisku wykonawczym bez użycia ton refleksji, aby go naprawić. Byłoby to paskudne rozwiązanie. – snicker

+0

Zrób to w innym AppDomain następnie? –

+0

Próbowałem owijać myObj = Activator.GetObject (...) w bloku try-catch, testując na wartość null, itp. Nie działa, ponieważ zwraca obiekt _TransparentProxy, czy serwer jest włączony, czy nie. Dopiero później, kiedy spróbujesz użyć myObj, przechyl się. Abjiheet ma właściwą odpowiedź, moim zdaniem. – IAbstract

0

Po prostu mała literówka w kodzie. Korekta jest następująca:

using System.Net.NetworkInformation; 
using System.Net; 
private static bool IsPortAvailable(int port) 
{ 
    IPGlobalProperties globalProperties = IPGlobalProperties.GetIPGlobalProperties(); 
    IPEndPoint[] activeListeners = globalProperties.GetActiveTcpListeners(); 
    if (activeListeners.Any(conn => conn.Port == port)) 
    { 
     return true; 
    } 
    return false; 
} 
0

Po zarejestrowaniu IpcServerChannel to sprawia, nazwanego potoku, aby komunikować się z nazwą nazwa portu wybranego za IpcServerChannel. Możesz przejrzeć listę nazwanych potoków, aby sprawdzić, czy jest tam Twoja nazwa portu.

System.IO.Directory.GetFiles(@"\\.\pipe\").Any((path) => path.Contains(@"\\.\pipe\" + pipeName)); 
Powiązane problemy