Hallo,
ich habe einen Application Server geschrieben, der auf Port 5000 kommunizieren soll.
Ich möchte dem Anwender nun mit dem passenden Client die Option geben, einen Server auszuwählen, der per Suche ermittelt wurde.
Ich weiß ehrlich gesagt nicht, wie ich das anstelle.
Jemand einen Tipp für mich?
Danke
> Codejunky <
domäne? wenn ja kannst du ja im Active directory suchen ou server z.B
"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."
Und wenn er in keiner Domäne ist?!
Wie suche ich also grundsätzlich im gesamten Netzwerk nach einem Offenen Port?
> Codejunky <
Irgendwoher brauchst Du eine Liste der IPs / Server.
Ob Du das nun durch ausprobieren selber erstellst oder eine Liste aus 3. Hand nimmst, dafür kenn ich die Rahmenbedingungen nicht.
Und dann halt den Port versuchen anzusprechen.
What'sUp, ein Programm / Service zu Serverüberwachung, nutzt eine Serverliste, die man selbst pflegen kann, oder wahlweise eine AD oder SQL-Schnittstelle, und pingt dann die einzelnen Server / Ports der Server ab, um deren Serviceaktivität zu testen und bei evtl. vorhandenen Downtimezeiten zu reagieren.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hallo JunkyXL,
das geht mit Broadcasts. Du kannst damit ein Paket an alle Geräte im selben Netzwerksegment senden. Aber Du solltest damit sehr sparsam umgehen, da das Netzwerk davon stark belastet wird. Am besten setzt Du Broadcasts nur ein, wenn der Benutzer explizit einen Suchen-Knopf drückt.
Wie man Broadcasts implementiert, findest Du in der Forensuche und im Netz.
Danke Rainbird.
Genau das will ich ja auch. Per Suchen Button soll ja dann am Programmstart ein verfügbarer Server gefunden und ausgewählt werden.
> Codejunky <
Hallo JunkyXL,
folgende Snippets könnten Dir weiterhelfen:
http://dotnet-snippets.de/dns/c-broadcast-senden-SID567.aspx
http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/baa3a5bb-2154-445f-965d-8a139dbe932a/
Danke für die Links, hatte das schon so umgesetzt, nur habe ich ein Problem beim Broadcasten. Wenn ich auf localhost Daten losschick, kommen diese ohne Probleme an.
Nehme ich wie es eigtl gefordert ist, die Broadcast Adresse, bekomme ich beim Senden eine SocketException: "An attempt was made to access a socket in a way forbidden by its access permissions"
using (Socket bcSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Broadcast, port);
//IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port); // <-- Damit funktionierts
bcSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 0);
// Send Broadcast
byte[] data = ASCIIEncoding.ASCII.GetBytes("hallo");
bcSocket.SendTo(data, endpoint); // <-- SocketException bei IPAddress.Broadcast
bcSocket.Close(500);
}
Der dazugehörige Listener (in separatem Thread):
listener = new UdpClient(port);
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, port);
while (true)
{
byte[] data = listener.Receive(ref endpoint);
if (data != null && data.Length > 0)
{
MessageBox.Show(String.Format("Response: '{0}'", ASCIIEncoding.ASCII.GetString(data)));
}
}
Habe ich etwas übersehen?
MSDN sagt zu dem Fehler:
Permission denied.
An attempt was made to access a socket in a way forbidden by its access permissions. An example is using a broadcast address for sendto without broadcast permission being set using setsockopt(SO_BROADCAST). Another possible reason for the WSAEACCES error is that when the bind function is called (on Windows NT 4 SP4 or later), another application, service, or kernel mode driver is bound to the same address with exclusive access. Such exclusive access is a new feature of Windows NT 4 SP4 and later, and is implemented by using the SO_EXCLUSIVEADDRUSE option.
Kann damit auch nicht mehr als vorher anfangen.
> Codejunky <
Welchen Port verwendest Du? Hast Du mit netstat geprüft, ob der Port nicht vielleicht durch eine andere Applikation belegt ist?
Der Application Server läuft auf 5000. Funktioniert auch, unsere Client-Anwendung greift ja auf den Server zu. 5000 geb ich auch als Portnummer in die Methoden rein..
Edit: Wenn ich nur an localhost sende, funktioniert es ja..
Habe es auch mit dem Administrator versucht. Selber Fehler.
> Codejunky <
Verwende für den Broadcast mal einen anderen Port.
Hallo!
Zur Not könntest du natürlich auch sowas umsetzen:
Allerdings solltest du die Sache einfach mal mit TCP probieren.
Du hast geschrieben, dass es mit 127.0.0.1 funktioniert, schickst du auch an die 255.255.255.255 oder nimmst du den directed Broadcast?
mfg, Rasta
Sogar meine Mailadresse ist .NET 🙂
Ich hab den Fehler:
bcSocket.EnableBroadcast = true;
muss gesetzt werden. Dann klappts zumindest bei mir mit der Adresse
IPAdress.Parse("255.255.255.255",40000);
Aber mit Port 5000 sollte es auch klappen.
EDIT: Es gab bei mir keine Exception mehr, ob jetzt das Paket auch angekommen ist, habe ich nicht überprüft.
mfg, Rasta
Sogar meine Mailadresse ist .NET 🙂
EnableBroadcast war die Lösung, danke!
Dumme Frage: Der Listener, der die Daten empfängt, muss ja dann in den Application Server implementiert werden, da von dort aus die Antwort folgen soll, richtig?
> Codejunky <
Ja, wenn du alle Server herausfinden möchtest, müssen alle Server eine Implementierung haben, damit Sie wissen, wie sie auf dein ominöses "Hallo" reagieren sollen. Wenn ihr allerdings eine automatische Softwareverteilung á la Novell Zenworks habt, sollte das kein Problem sein, dann bekommt einfach jeder Server das verteilt. Möglicherweise gibt es allerdings auch einen String, den du sendest, der dann eine Antwort auslöst, das wäre ideal(Beispiel: Ein SMTP-Mailserver antwortet auf "HELO" z.b. mit seinem Namen und "250 Hello <Clientname>, nice to meet you".). Da ihr aber bestimmt nicht nur Mailserver im Haus habt, ist diese Methode nicht universell genug. Aber vllt gibt es ja auf TCP/IP Ebene einen Befehl (Scheisse bin ich dumm, sende einfach n ping...).
mfg, Rasta
Sogar meine Mailadresse ist .NET 🙂
Ping an unbekannt? 🙂
Das "hallo" ist ja nur fiktiv, da kommt schon noch was gescheites rein.
Ich brauch ne geballte Antwort. Am Besten ein Objekt, was die nötigen Informationen über den Server beinhaltet, die dann der suchende Client entgegennimmt und anzeigt. Sollte wohl kein Problem sein
> Codejunky <
http://de.wikipedia.org/wiki/Ping_(Daten%C3%BCbertragung)
Da steht ne ganze Menge drin, unter anderem die Adresse etc. Du muss halt unterscheiden: Ping (programm), ping(ICMP-Befehl).
du musst den Befehl senden.
mfg, Rasta
Sogar meine Mailadresse ist .NET 🙂
Ich habe da auch noch was gefunden, ob es dir was nützt, weiss ich nicht:
Ping p = new Ping();
using System.Net.NetworkInformation;
Das geht aber wiederum nicht für einen Broadcast (zumindest das Emfangen. Senden konnte ich, habe aber immer nur eine IP-Adresse zurückbekommen.).
Den Listener musst du dir also selbst bauen, mit dieser Klasse hast du aber einen praktischen Zweizeiler zum pingen. Mit dem Ping kann man auch die Adresse abfragen, von der die Antwort kommt. Mit dieser IP kannst du dir ja dann alle Infos holen, indem du den Server "fragst".
mfg, Rasta
Sogar meine Mailadresse ist .NET 🙂
Heute ist dein Glückstag xD
Mich hat das ganze selbst interessiert und daher habe ich mal was zusammengeflickt:
Ping p = new Ping();
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp);
byte[] b = new byte[5000];
EndPoint ep = (EndPoint)new IPEndPoint(IPAddress.Any,0);
s.Bind(ep);
List<EndPoint> antworten = new List<EndPoint>();
p.SendAsync(IPAddress.Broadcast, "Hallo");
for (int i = 0; i < 10; i++)
{
s.ReceiveFrom(b, ref ep);
if (!(antworten.Contains(ep)))
{
antworten.Add(ep);
}
}
List<long> lo = new List<long>();
foreach (EndPoint end in antworten)
{
lo.Add(IPAddress.Parse(end.ToString().Replace(":0", "")).Address);
}
lo.Sort();
foreach (long lon in lo)
{
IPAddress sf = new IPAddress(lon);
email.Text += sf.ToString() + Environment.NewLine;
}
Du brauchst zum ausführen eine Richtextbox oder sowas. Alternativ kannst du auch email.Text mit einer List<string> oder einem Array etc. ersetzen.
Die Methode ist unvollständig:
1.Die Sortierung ist leicht falschherum
2.Es werden nur 10 Adressen angepingt, ich wusste so auf die schnelle nicht, wie ich herausfinden soll, ob noch Antworten hereinkommen(Vorschlag: Das ganze in einen Thread packen, den 5 Sek laufen lassen und dann beenden und die Ergebnisse auslesen).
3.Schlechte Programmierung(Variablennamen 🙂)
@ ADMINS: Vllt ist das, wenn es etwas vervollständigt wird, ein sinnvolles Snippet für die Abteilung "C#-Snippets". Die vorstellbaren Anwendungen sind vielfältig, z.b. alle Mailserver anpingen, alle IPv6-fähigen Clients ansprechen etc...
@ JunkyXL: Viel Spaß damit. Das ganze erkläre ich hiermit zur Beerware 😉
mfg, Rasta
Sogar meine Mailadresse ist .NET 🙂
Heute ist dein Glückstag xD
Mich hat das ganze selbst interessiert und daher habe ich mal was zusammengeflickt:
Ping broadcasten und empfangen
mfg, Rasta
Sogar meine Mailadresse ist .NET 🙂
Wenn du damit meinen Geburtstag meintest, dann danke 🙂
Ich finde dein Beispiel etwas verwirrend.. Du sendest einen Ping und im selben Codeabschnitt machst du dich gleich daran, diesen Ping abzufangen.
Dabei musst du Glück haben, wenn du die ersten Pings empfängst.
Deshalb:
setze p.Async() in den Hauptteil und die Schleife mit s.ReceiveFrom(b, ref ep); sollte bereits ausgeführt werden bevor p.Async() aufgerufen wird.
> Codejunky <
Prinzipiell hast du schon Recht, aber ich hab ping.send direkt über die empfangsschleife gesetzt. Ich hab bisher gedacht, dass die ping-laufzeit deutlich größer ist, als die zeit, die der PC zum deklarieren der paar variablen braucht. Ich hab das ganze noch ein wenig angepasst, aber das auslagern in nen anderen Thread hab ich noch nicht gemacht. Kannst du ja machen^^
EDIT: Glückwunsch!
Sogar meine Mailadresse ist .NET 🙂