solch eine ähnliche programm-stuktur habe ich in einem Programm verarbeitet... allerdings dient es jetzt nur zu abfrage zwecken... ich möchte eine Funktiom einbauen, in der die user dieses programms miteinander kommunizieren können... also client-nr 4 will jetzt beispielsweise eine nachricht an client-nr 27 schicken...
1. muss eine ID oder logindaten erkennen
2. muss die ID mit den Clienten-nr abgleichen
3. die nachricht an diesen clienten senden*
*hiermit habe ich bedenken, dass es funktioniert
bevor ich mich jetzt ans große programmieren mache, wollte ich wissen, ob dies möglich ist...
im prinzip benutze ich das gleiche system (mehr oder weniger), nur dass die verbindung dauerhaft ist...
Als erstes danke für das Tutorial! Wäre froh gewsen, wäre dies schon anfang Jahr hier online gewesen aber so habe ich mich selbst wohl noch tiefer mit diesem Thema befasst.
Sehe ich es richtig, dass du kein Thread Array erstellst, sobald eine Verbindung eingeht? Ich glaube nämlich dies ist der Schlüssel zur Kommunikation zwischen den verschiendenen Clients wie von mir und Sypher gewollt.
Ich glaube theoretisch kann man mittels invoke zwischen den Threads hin und her springen... Wäre froh um Bestätigung oder Korrektur.
Im Artikelforum kann man zwar als Benutzer keinen neuen Thread erstellen, aber man kann auf einen bestehenden Thread antworten (zumindest sollte es gehen). Deshalb hätte die Diskussion auch dort stattfinden können. Da ich aber durchaus sinnvoll ist, den Artikel für sich stehen zu lassen und die Diskussion auszulagern, habe ich den Artikel selbst geschlossen.
Ich hol' jetzt mal ein wenig aus, um sicherzugehen, dass wir uns nicht falsch verstehen, also bitte nicht als Belehrung betrachten ;-) :
Also grundlegend ist diese Komponente nicht als Kommunikationsmöglichkeit zwischen Clients gedacht, sondern als kurzfristige Client-/Server-Kommunikation. D.h. ein Client greift kurzfristig auf Dienste eines Servers zu, kriegt evtl. noch eine Antwort, danach ist die Kommunikation beendet.
Was Vido und sypher ansprechen, ist eher eine Peer-to-Peer-Verbindung, ähnlich den Tauschbörsen oder Chat-Programmen, wo es nicht zwingend einen zentralen Server gibt, höchstens einige Knoten, welche die Verbindungen einleiten, sonst aber den Clients funktional "unterlegen" sind.
Bzgl. dieser Kommunikation und einer längerfristigen Client-/Server-Kommunikation, d.h. z.B. kein automatischer Abbau oder ein wesentlich höherer TimeOut-Wert habe ich als nächstes geplant, entweder als neues Tutorial oder als Fortsetzung zum o.g. Tutorial.
Was Vido und sypher ansprechen, ist eher eine Peer-to-Peer-Verbindung, ähnlich den Tauschbörsen oder Chat-Programmen, wo es nicht zwingend einen zentralen Server gibt, höchstens einige Knoten, welche die Verbindungen einleiten, sonst aber den Clients funktional "unterlegen" sind.
Nein ich spreche keine Peer-to-Peer Verbindung an. Ich möchte tatsächlich zwischen den Clients kommunizieren ohne, dass die miteinander direkt Verbunden sind. Ich habe dies nun realisiert und werde mitte Juli selbst ein kleines Turtorial dazu veröffentlichen.
Hier eine kleines Preview:
// Erstelle ein Array in dem die Verbindung erstellt werden
private static ArrayList threads = new ArrayList();
// Neuen Client IM Array instanzieren. Dabei übergebe ich den TCPClient
threads.Add(new InClient(c));
// Das kommunizieren zwischen den Clients läuft in einer Schleife ab:
foreach (InClient inclient in threads)
{
inclient.sende_nachricht("hallo");
}
Selbstverständlich ist dies nur die Grundlage! Man muss noch mit Abfragen ob es der richtige Client ist, etc...
Mein Tipp: Das ist von den Anforderung de facto identisch mit einem klassischen Multi-User-Chat. Und Netzwerk-Chats in .NET gibts wie Sand am Meer.... muss man nur nach googeln.
Bei "härteren" MU-Games müßte man sich schon eher um Performance (vielleicht UDP anstelle von TCP) Gedanken machen. High-Level-Protokolle wie WebServices würden dann auch ausscheiden.
Welche Technologie man in diesem Szenario einsetzt ist fast Wurscht. Gehen tut alles. Es ist nur ein Frage der Plattform und vielleicht der Sicherheit (Durchdringung von Firmen-Firewalls).
Die vermutlich einfachste Implementierung wäre über Remoting. Für den Rückkanal bieten sich dann Events (eine Nachricht an alle wie bei Chat) bzw. Delegates (gezielte Benachrichtigung eines Clients) an.
ich habe die Komponente ausprobiert.
Das Senden der kleinen Nachricht scheint einwandfrei zu funktionieren.
Leider bekomme ich immer beim Senden der großen Message einen Übertragungsfehler. Nach dem Übertragungsfehler hängt die Komponente und läßt sich nur noch abschiessen.
Gibt es mittlerweile eine aktualisierte Version bzw. was könnte bei mir falsch laufen? (Ich probiere Client und Server direkt auf dem gleichen Rechner (per 127.0.0.1)) Von 10x funktioniert die große Nachricht 1x und 9x nicht.
Gruß
Torsten
There are 10 diffent types of people in this world: Those who understand binary and those who don't....
hab das mal ausprobiert und für gut befunden
nein, finde es echt klasse, auch die Idee die dahinter steckt. jedoch kann ich die ServerGui nicht beenden, die Form schloss sich zwar aber der prozess (insgesamt 3 Threads) wurde nicht beendet.
Also:
Bzgl. der grossen Nachrichten werd' ich dass demnächst nochmal überprüfen, hab' allerdings grad' noch ein paar Prüfungen.
Wie gross sind den die Daten? Ich hatte es mal mit 2MB probiert, da hat's funktioniert.
Aber wenn's nicht funktioniert, weis ich evtl. schon, woran es liegt: Die Daten müssen fragmentiert werden, da die Socket-API nur einen begrenzten Puffer hat ( ich glaub' 16KB ). Leider hab' ich keine Möglichkeit gefunden, diesen Wert abzufragen.
D.h. liegt der Fehler wahrscheinlich beim Senden der Nachricht.
Aber wie gesagt: Ich prüfe das ....
Bzgl. der "Unmöglichkeit", die ServerGui zu schliessen, liegt dies einfach nur daran, dass die Threads für die Client-Verbindungen nicht beendet werden.
Dies muss man explizit durchführen, wobei ich da mittlerweile ein wenig verändert habe.
Ich werd' auch dass nochmal neu ausarbeiten, und dann das vorhandene Tut. erweitern.
Aber vergebt mir, wenn ich mich bei dem Wetter nicht ganz so beeile ;-)
Interessant fände ich z.B. wie ich größere, binäre Datein verschicke (mehrere hintereineander) und die Gegenstelle diese ordnungsgemäss empfängt und speichert ;-).
Ich habe einfach mal folgendes probiert :
if (mem.Length>0)
{
if (mem.Length==4)
if (System.Text.Encoding.ASCII.GetString(mem.ToArray(),0,4)=="quit")
{
instanceOfClass.closeConnection();
break;
}
//Console.WriteLine("send {0} bytes",mem.Length);
instanceOfClass.Receive(mem.ToArray());
// Von mir------------------------------------
image = Image.FromStream(mem);
image.Save(@"F:\TESTBILD.jpg"); //ca 2,5MB
// Von mir ENDE ------------------------------
mem.Seek(0,SeekOrigin.Begin);
mem.SetLength(0);
TimeOut=0;
}
und auf client Seite :
private void SendeBild_Click(object sender, EventArgs e)
{
MemoryStream mem = new MemoryStream();
BilderBox1.Image.Save(mem,ImageFormat.Jpeg );
byte[] rawData = mem.ToArray();
client.send(rawData);
}
Das Bild kommt nur teilweise an ;-(.
Wie kann man sowas ralisieren ?
Später sollen dann auf Client seite in einer Schleife mehrere Bilde hintereinander geschickt werden.
Wie halte ich die Streams auseinander ?
In einem Buffer, der gesendet wird kann doch auch mal das Ende des Einen Bildes und der Anfang des nächsten Bildes sein oder sehe ich da was falsch ?
Habe mal irgend was aufgeschnappt, das man dann erst die Größe schickt und dann
den Stream.
Dann schicke ich die Größe meinetwegen '20000000' , danach das Bild , so jetzt kommt ein Buffer an , wo 20000000 drinn steht und danach die Bildinformation wie weiss ich wie weit meine Größe in dem Buffer geht ?
Baue ich mir selber Trennzeichen ein ?
Mache ich auf Client Seite eine Pause, damit ich in den Timeout vom Server laufe ?
Danke
Ylirebus
Die Bugs verhalten sich proportional zu den Codezeilen und nehmen exponential zu.(Ich bin nicht doof, ich denke nur anders. ;-))
Ich fühle mich als wäre ich diagonal in einem Paralleluniversum abgestellt worden.
Hallo, erstmal vielen Dank für das tolle Tutorium.
Ich hab allerdings eine Frage, bzw. ein Problem auf der Server-Seite. Das der Server in einer Schleife auf eingehende Client-Verbindungen warten muß, ist mir klar. Und das man das ohne das Programm zu blockieren in einem Thread durchführen sollte, ist auch verständlich. Ich bin nur über folgende Codezeilen verwundert:
listener.Start();
// Solange Clients akzeptieren, bis das
// angegebene Maximum erreicht ist
while (true)
{
while (!listener.Pending()) {Thread.Sleep(sleepTime);}
Socket newSocket = listener.AcceptSocket();
if (newSocket != null)
{
// Mitteilung bzgl. neuer Clientverbindung
System.Console.WriteLine("Neue Client-Verbindung ("+
"IP: "+newSocket.RemoteEndPoint+", "+
"Port "+((IPEndPoint)newSocket.LocalEndPoint).Port.ToString()+")");
serverInstance newConnection = new serverInstance(newSocket);
Clients.Add(newConnection);
}
}
Das abhören geschieht über eine while(true) Schleife, ohne Abbruchbedingung (dafür allein sollte man doch jemanden steinigen, oder??). Und daher resultiert mein Problem. Beim Schließen meines Programms läuft offensichtlich diese Schleife weiter (ich hab im Taskmanager gesehen, dass der Prozess beim beenden des Programms nicht geschlossen wird). Der zugehörige Thread geht in den Status WaitJoinSleep (ohne Gewähr). Bau ich Testweise eine Abbruchbedingung in die Schleife ein, wird alles ordnungsgemäß beendet.
zb.
listener.Start();
// Solange Clients akzeptieren, bis das
// angegebene Maximum erreicht ist
int counter = 0;
while (counter<5)
{
while (!listener.Pending()) {Thread.Sleep(sleepTime);}
Socket newSocket = listener.AcceptSocket();
if (newSocket != null)
{
// Mitteilung bzgl. neuer Clientverbindung
System.Console.WriteLine("Neue Client-Verbindung ("+
"IP: "+newSocket.RemoteEndPoint+", "+
"Port "+((IPEndPoint)newSocket.LocalEndPoint).Port.ToString()+")");
serverInstance newConnection = new serverInstance(newSocket);
Clients.Add(newConnection);
counter++;
}
}
Diese Bedingung beendet die while Schleife wenn 5 Clients sich angemeldet haben. Aber das ist ja nicht Sinn des Servers.
Also wie sollte man sauber diesen Thread /Schleife verlassen? Ruf ich Thread.Abort() auf, wechselt der Status in WaitSleepJoin / Abort Requested.... und nix passiert.
Entweder du schiesst den Thread per Abort() ab, oder du definierst ihn als Background-Thread, dann macht das .NET automatisch bei App-Ende. Eine simple Abbruchbedingung im While reicht jedenfalls nicht, weil AcceptSocket()-Socket ja blockiert. Die Beendigung des Threads würde also nur dann Eintreten, wenn sich ein neuer Client verbunden hat. Dritte Möglichkeit ist BeginAcceptSocket in Kombination mit einem Sync-Objekt, welches den Abbruch signalisiert.
Danke für die Antwort. Also ein paar Möglichkeiten hast du mir ja jetzt aufgezählt. Allerdings frag ich mich, wieso das im Tutorial nicht erwähnt, oder dann anders gemacht wurde.
Gruß, Taner
PS: Der Fehler lag bei meinem Code ..., und ich will dem Autor des Tutorial auch nix vorwerfen :-) Ich freu mich über jedes gut geschriebenes Tutorial.
ich sitz hier verzweifelter art und weise an ner client-server-anwendung:
ein gerät ist ein normaler pc und dazu kommt noch ein pda mit nem windows ce 4.2 dotNet (CF 1.0 SP3 soweit ich weiß).
(btw: ich habe schon mehrere erfolgreiche anwendungen für dieses gerät geschrieben...bin also nicht grad n newbee in der materie)
ich habe das beispiel hier ausm forum erfolgreich auf dem pc compiliert und ausprobiert.
ich kann auch ohne probleme server und client auf dem pda laufen lassen.
ABER:
sobald ich vom pda (client) auf den server (pc) zugreifen will, kommt ne socketexception geflogen. (hab auch schon andere socket-examples ausprobiert)
firewalls ist aus. geräte können sich untereinander anpingen. WAS MACH ICH FALSCH??? so langsam verlier ich jegliches vertrauen in mich selbst *möööp*
ich bin über alle hinweise sehr dankbar!
mfg, der tobi
[edit]
wenn der server auf dem pda läuft, dann kann ich mich connecten!!! ist da irgendwas auf dem pda, was nen verbindungsaufbau nach außen verhindert?
mit dem internet-explorer (aufm pda) kann ich auf den pc zugreifen.
wenn die client-server-anwednung über port 80 geht, funktioniert's trotzdem nicht.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von justin.caseof am .
Gabs da nicht was mit Work, Internet noch was anderes in den Netzwerkeinstellungen von Pocket PC? Schraub doch da mal rum. Ansonsten riecht das normalerweise sehr nach Firewall.
ich bin auch erst von firewall ausgegangen, aber da ist echt nichts am laufen.
-->mit iexplorer (auf pda) zum pc geht irgendwas (der server checkt was), aber mit der client anwendung aufm pda zu serverport 80 aufm pc geht nix.
ich erschieß mich heut noch *mööp*
[edit]
die sache läuft immernoch nicht...
es MUSS an der .Net Socket geschichte für das compact framework liegen. was anderes kann ich mir nicht erklären. firewall ist deshalb quatsch weil ja socketverbindungen vom iexplorer (auf pda) aus funktionieren und nur nicht mit meinem programm bzw. der testanwendung hier ausm forum. außerdem kann ich mich wenn der pda server ist auch zu ihm connecten.
ich probier morgen mal das CF 2.0 aus...wenn's denn auf CE 4.2 läuft...da hab ich noch keinen plan.
[nochma_edit]
java sockets laufen!!! es is echt 100% die Socket geschichte vom .Net CF!
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von justin.caseof am .
bei mir funktioniert das garnicht (ich benutzte die version von tom-essen)
hab beide programme auf dem gleichen pc laufen
der Server läuft in der Schleife vor sich hin
aber der client bleibt in der Connect methode hängen und gibt nach etwa 4 sek eine ausnahme raus.
firewall kanns nicht sein (hab keine)
vllt ist es windows schuld (diese version hat des-öfteren macken, vorallem wenn es um netzwerk dinge geht)
ich werd mal an nem anderen PC gugen ob es da läuft
aber vllt kennt einer das problem und weiß abhilfe
MfG janismac
EDIT:
habs mal an nem anderen PC ausprobiet, klappt auch nicht
was ist falsch????
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von janismac am .
Da ich z.Zt. an einem Projekt arbeite, welches die C/S-Komponente verwendet, werd' ich mal versuchen, das Tutorial und die Komponente ein wenig zu überarbeiten und zu erweitern.
Kann allerdings etwas dauern, bin im schreiben nicht unbedingt der Fleißigste ...
Ich hab mir das Tutoiral heruntergeladen, und wollte anfangs eigentlich nichts anderes machen als auf der ServerGui, in einer richTextBox, alle vorgänge "mitloggen" zu lassen.
Ich dachte eigentlich das ich das "ganz einfach" über
server = new Server(typeof(ServerGui.server_class));
server.status.messageEvents += new MessageEvent(status_messageEvents);
realisieren kann, allerdings seh ich in der rtb dann nur den Namespace namen "Server.Gui" .
Kann mir jemand vielleicht auf die Sprüngen helfen?
Gruß Kalleberlin
If u want to finish first, u have to finish first.
public Server(Type serverClass)
{
Type it = typeof(serverInterface);
// Zentralen Eventhandler registrieren
status.messageEvents+= new MessageEvent(Server_MessageEvents);
...
Mein Problem ist, das ich bei status.message... nicht finde, wo status deklariert ist.
Ich finde auch nichts, was damit zu tun haben könnte.
Und ich bekomme folgende Fehlermeldung beim ausführen unter VS2008:
Zitat
System.InvalidOperationException was unhandled
Message="Das Protokoll für die Quelle TcpServer kann nicht geöffnet werden. Möglicherweise haben Sie keinen Schreibzugriff."
Source="System"
Habe nichts verändert.
Wäre es möglich dass jemand das Tutorial für die Verhältnisse und Neuerungen in VS2008 und dem FW3.5 anpasst?
Hm, sehr nettes Tutorial. Funktioniert auch super! Nur ein Problem habe ich, wie entferne ich eine ServerInstanz aus dem "clients"-Array wenn der client die Verbindung trennt? Jetzt bekomm ich eine nullpointer exception.
thx SunboX
Actionscript ist die Möglichkeit, postmaterielles Basteln zum Lebensstil zu machen.
Künstliche Intelligenz ist leichter zu ertragen, als natürliche Dummheit!
ich bin neu in myCSharp.de, auch beschäftige ich mich seit kurzem mit C#. Und schon muss ich mich mit TCP Socket verbindung vertraut machen. Nun habe ich dieses Tutorial entdeckt, welches mir sehr viel verständlich gemacht hat. Leider muss ich sagen, dass der Quellcode, der dabei ist, nicht in VS 2005 compilieren lässt, und somit nicht lauffähig ist. Meine Bitte an Diejenigen, könnte mir jemand Quellcode Version für .Net 2005 zukommen lassen.
Ich habe es soweit in .Net 2005 konvertieren können, bloß der Server lässt sich nicht starten auch kann ich den Client mit Server nicht verbinden.