Hallo, ich habe folgendes Anliegen:
Ich programmiere zur Zeit einen Messenger zum senden von Text bzw Daten.
Der Austausch zwischen Server und Client funktioniert zum Teil. Texte können bereits gesendet werden. Sowohl privat als auch öffentlich.
Für das senden habe ich mir ein kleines Protokoll angelegt, damit der Server die Daten verwalten kann.
Senden von Text:
Serverseite
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| private void SendTelegram(TcpClient receiverName, string telegram) { try { NetworkStream stream = receiverName.GetStream(); StreamWriter writer = new StreamWriter(stream); stream.Flush(); writer.WriteLine(telegram); writer.Flush(); } catch (Exception) { if (allClients.ContainsKey(receiverName)) { allClients.Remove(receiverName); } } } |
Das telegram sieht dann beispielsweise so aus:
SND_PRV|User1|Nachricht
Als erstes wird das Comand angeführt, gefolgt vom Empfänger und im anschluss die eigentliche Nachricht.
Empfangen der Nachricht
Client:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| private void ParseMessage() { while (isReading) { try { NetworkStream stream = client.GetStream(); StreamReader reader = new StreamReader(stream); string telegram = reader.ReadLine();
if (!String.IsNullOrEmpty(telegram)) { string[] message = telegram.Split('|'); string command = message[0];
switch(command) { case "MSG_PRV": { writeConsole("--> " + message[1] + ": " + message [2]);
break; } case "MSG_PUB": {
... |
So funtioniert das senden und Empfangen von Nachrichten in beide Richtungen. Nun soll das Programm erweitert werden, um Dateien zu versenden.
Jetzt stehe ich aber vor folgendem Problem.
Zum senden einer Datei würde ich einen Filestream nutzen. Die Datei wird in den Stream geladen und verschickt. Nun betshet das Problem das ich kein Comand verschicken würde. Daher dachte ich mir, es könnte funktionieren, wenn ich die Datei in ein Byte-Array aufteile. Das Array soll dann erweitert werden, damit ich ein Comand vor die Datei-Daten hängen kann.
Wird dieses Byte-Array nun so verschickt, werden beim Senden mehrere Pakete geschickt aber nur im ersten steht das Comand. Also haben alle weiteren Pakete kein Comand und der Client kann die Pakete nicht zuordnen.
Nun kam mir die Idee ein Flag zu setzen, welches aussagt, dass solange Packete von der Datei kommen immer wieder in ein Case für Dateien springt. Sobald alle Pakete empfangen wurden soll das Flag zurück gesetzt werden und der Client kann wieder Text bzw. Dateien empfangen.
Ansatzweise funktionierte dies auch schon, aber die Daten, welche empfangen werden sind entweder unbrauchbar oder werden falsch interpretiert.
Senden von Dateien, Serverseite:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| private void SendFile(string data, TcpClient destination) { string command = "SND_FILE|";
NetworkStream nwStream = destination.GetStream(); FileStream fStream = File.OpenRead(data);
byte[] bytes = new byte[fStream.Length];
fStream.Read(bytes, 0, bytes.Length);
byte[] cmdSize = new byte[command.Length]; cmdSize = Encoding.ASCII.GetBytes(command);
Array.Resize(ref bytes, (bytes.Length + cmdSize.Length));
Buffer.BlockCopy(bytes, 0, bytes, command.Length, (int)fStream.Length); Buffer.BlockCopy(cmdSize, 0, bytes, 0, cmdSize.Length);
nwStream.Write(bytes, 0, bytes.Length);
writeConsole("Data send complete!");
nwStream.Close(); fStream.Close(); } |
Empfangen von Dateien, Client:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52:
| private void ParseMessage() { while (isReading) { try { NetworkStream stream = client.GetStream(); StreamReader reader = new StreamReader(stream); string telegram = reader.ReadLine();
if (!String.IsNullOrEmpty(telegram)) { string[] message = telegram.Split('|'); string command = message[0];
if (getFile) { command = "SND_FILE"; }
switch(command) {
.....
case "SND_FILE": { if (!getFile) { writeConsole("Getting file!"); getFile = true; fs = new FileStream(pathToSave, FileMode.Create); fileData = new byte[1000]; } fileData = Encoding.ASCII.GetBytes(telegram);
fs.Write(fileData, 0, fileData.Length); break; } default: { writeConsole("Unknown comand!"); } } else { getFile = false; fs.Close(); } |
Es wäre nett wenn hier Vorschläge gegeben werden, wie ich das Problem lösen kann. Ich weis nicht ob der Ansatz überhaupt richtig ist oder totaler Käse. Da ich dabei bin mich in dieses Thema eigenständig ein zu lesen gibt es durchaus viele Dinge mit denen ich mir vieles erleichtern könnte oder welche sinnvoller sind. Aber ich kann es mir auch nicht aus den Fingern saugen.
Vielen Dank
Gruß