2012-04-01 9 views
3

Ich habe versucht, eine Datei von einem Client an eine Server-Anwendung mit der TCPClient-Klasse in C# zu senden. Bevor ich die eigentlichen Daten sende, sende ich einige zusätzliche Informationen wie die genaue Dateigröße und den Dateinamen, damit die Serveranwendung weiß, wieviel zu lesen ist. Die lustige Sache ist, dass alles in Ordnung war, als ich es auf 127.0.0.1 getestet habe - sobald ich die IP-Adresse durch die tatsächliche ersetzte, konnte der Server nur ungefähr 1,5 KByte der gesendeten Daten lesen. Es erhält immer noch den Dateinamen und die Dateigröße, aber es gibt keine Möglichkeit, die tatsächlichen Daten abzurufen.Senden einer Datei mit TCPClient und NetworkStream in C#

Zu Testzwecken ersetzte ich das Bild, das ich senden wollte, mit einer einfachen Zeichenfolge und die Übertragung ging gut, also nehme ich an, es gibt ein Problem beim Senden und Empfangen der Datenblöcke, aber ich bekomme keine Ausnahmen auf der Clientseite entweder.

Wer hat eine Idee? Prost!

Edit:

Dank so weit, ist es das, was ich codewise bekommen haben. Für die Auftraggeber:

 IPAddress ipAddress = IPAddress.Parse("xx.xx.xx.xx"); 
     int port = 3003; 
     int bufferSize = 1024; 

     TcpClient client = new TcpClient(); 
     NetworkStream netStream; 

     // Connect to server 
     try 
     { 
      client.Connect(new IPEndPoint(ipAddress, port)); 

     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 

     netStream = client.GetStream(); 

     // Read bytes from image 
     byte[] data = File.ReadAllBytes("C:\\Users\\Dan\\Desktop\\asdf.jpg"); 

     // Build the package 
     byte[] dataLength = BitConverter.GetBytes(data.Length); 
     byte[] package = new byte[4 + data.Length]; 
     dataLength.CopyTo(package, 0); 
     data.CopyTo(package, 4); 

     // Send to server 
     int bytesSent = 0; 
     int bytesLeft = package.Length; 

     while (bytesLeft > 0) 
     { 

      int nextPacketSize = (bytesLeft > bufferSize) ? bufferSize : bytesLeft; 

      netStream.Write(package, bytesSent, nextPacketSize); 
      bytesSent += nextPacketSize; 
      bytesLeft -= nextPacketSize; 

     } 

     // Clean up 
     netStream.Close(); 
     client.Close(); 

und den Server:

 TcpListener listen = new TcpListener(3003); 
     TcpClient client; 
     int bufferSize = 1024; 
     NetworkStream netStream; 
     int bytesRead = 0; 
     int allBytesRead = 0; 

     // Start listening 
     listen.Start(); 

     // Accept client 
     client = listen.AcceptTcpClient(); 
     netStream = client.GetStream(); 

     // Read length of incoming data 
     byte[] length = new byte[4]; 
     bytesRead = netStream.Read(length, 0, 4); 
     int dataLength = BitConverter.ToInt32(length,0); 

     // Read the data 
     int bytesLeft = dataLength; 
     byte[] data = new byte[dataLength]; 

     while (bytesLeft > 0) 
     { 

      int nextPacketSize = (bytesLeft > bufferSize) ? bufferSize : bytesLeft; 

      bytesRead = netStream.Read(data, allBytesRead, nextPacketSize); 
      allBytesRead += bytesRead; 
      bytesLeft -= bytesRead; 

     } 

     // Save image to desktop 
     File.WriteAllBytes("C:\\Users\\Dan\\Desktop\\tcpimage.jpg", data); 

     // Clean up 
     netStream.Close(); 
     client.Close(); 
+0

Bitte schreiben Sie den Code - sonst könnten wir alle Arten von Sackgassen hinuntergehen. –

+0

Ich fürchte, wir müssen etwas Code sehen. Das Testen lokal und remote kann sehr unterschiedliche Ergebnisse liefern (zum Beispiel ist das Testen lokal so wie direkt, so dass Sie die üblichen Probleme nicht schnell genug haben) – Polity

+0

Haben Sie tatsächlich in einer Schleife gelesen, oder haben Sie nur 'Read' einmal aufgerufen? Sie können auch 'BinaryReader.ReadToEnd' verwenden. – CodesInChaos

Antwort

1

Etwa 1,5 KiB klingt wie 1500 Bytes, "der größte von Ethernet auf der Vermittlungsschicht erlaubt". Das ist der maximum transmission unit (mtu), der Ihren Netzwerkstapel zwingt, Ihre Datei in mehrere kleine Pakete aufzuteilen.

Sie müssen die NetworkStream.Read in einer Schleife anrufen, um jedes Paket zu lesen. Es gibt Beispielcode von diesem bei MSDN.

Kombinieren Sie dies mit dem Standardverhalten von .NET; Sie können kleinere Pakete konsolidieren, um die Menge der gesendeten Pakete zu reduzieren, und Sie werden dieses Verhalten auch beim Senden kleinerer Pakete sehen. Dies kann mit oder mit kleineren Scoped-Socket-Optionen gesteuert werden.

+0

ServicePointManager wird nur mit HTTP-Verbindungen verwendet. –

0

Ich habe einen Teil Ihres Codes für ein Testnetzwerk verwendet, an dem ich gerade arbeite. Ich habe ein paar Dinge optimiert, um die Anforderungen meines Projekts zu erfüllen, aber eine Änderung, die ich an dem ursprünglichen Code vornehmen musste, ist das Hinzufügen einer "-4" zu der Zeile, die die Variable BytesLeft gesetzt hat. Danach hat der Code funktioniert. Meine Testdatei ist 52KB & wurde erfolgreich übertragen.

 // Read the data 
    int bytesLeft = dataLength-4; 
    byte[] data = new byte[dataLength]; 
0

Ok, weiß nicht, was ich hier mache, aber bei jemand nutzt diese als Referenz vorgemerkt.

Ich habe von unnötigen Kopieren befreit und eine sehr wichtige Verbesserung getan.Ihr Weg zu calc nextPacketSize ist nicht abgeschlossen, da es weniger Daten als 1024 vorhanden sein könnte, und Sie erhalten zusätzliche Nullen zwischen diesen Brocken (ich hatte eine Menge Kopfschmerzen damit, jetzt so glücklich, herauszufinden)

ich habe sie als Funktion für mehrere Dateien benötigt, so ist hier Code:

Client

dieses

public void sendData(byte[] data, NetworkStream stream) 
{ 
    int bufferSize = 1024; 

    byte[] dataLength = BitConverter.GetBytes(data.Length); 

    stream.Write(dataLength, 0, 4); 

    int bytesSent = 0; 
    int bytesLeft = data.Length; 

    while (bytesLeft > 0) 
    { 
     int curDataSize = Math.Min(bufferSize, bytesLeft); 

     stream.Write(data, bytesSent, curDataSize); 

     bytesSent += curDataSize; 
     bytesLeft -= curDataSize; 
    } 
} 

Server ist fast das gleiche

public byte[] getData(TcpClient client) 
{ 
    NetworkStream stream = client.GetStream(); 

    byte[] fileSizeBytes = new byte[4]; 
    int bytes = stream.Read(fileSizeBytes, 0, 4); 
    int dataLength = BitConverter.ToInt32(fileSizeBytes, 0); 

    int bytesLeft = dataLength; 
    byte[] data = new byte[dataLength]; 

    int bufferSize = 1024; 
    int bytesRead = 0; 

    while (bytesLeft > 0) 
    { 
     int curDataSize = Math.Min(bufferSize, bytesLeft); 
     if (client.Available < curDataSize) 
      curDataSize = client.Available; //This saved me 

     bytes = stream.Read(data, bytesRead, curDataSize); 

     bytesRead += curDataSize; 
     bytesLeft -= curDataSize; 
    } 

    return data; 
} 
Verwandte Themen