[C#] - TCP File Server und Client


s8jascho

Grünschnabel
Hallo.

Ich habe mal wieder ein Problem.
Ich habe einen TCP-Server und einen dazugehörigen Client. Erst starte ich den Server, dann den Client, die Verbindung wird aufgebaut und dann versuche ich ein Textdatei zu übertragen.
Der Server sagt er öffnet die Datei, der Client sagt er sendet sie. Ich habe im Ordner des Programms vom Client eine 16KB große Datei die übertragen werden soll.
Es passiert jedoch nichts. Nach 10 Minuten hat sich auch nichts getan und eigentlich sollten 16KB ja realtiv schnell übertragen werden bei einer Verbindung auf dem eigenen Rechner.

Vielleicht könnt ihr euch das mal ansehen und vielleicht findet ihr ja auch einen Fehler, mir kommt das alles nämlich sehr seltsam vor.

Servercode
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;


namespace Demo_LAMT_TCPServer_3
{
    public class AsynchTcpNetworkFileServer
    {
        class ClientHandler
        {
            private const int bufferSize = 256;
            private byte[] buffer;
            private Socket socket;
            private NetworkStream networkStream;
            private Stream inputstream;
            private AsyncCallback callbackRead;
            private AsyncCallback callbackWrite;
            private AsyncCallback myFileCallback;


            //  Constructor
            public ClientHandler(Socket socketForClient)
            {
                // initialize member variable
                socket = socketForClient;

                //  initialize buffer for file content
                buffer = new byte[256];

                //  create networkStream
                networkStream = new NetworkStream(socketForClient);

                //  set file callback for reading
                myFileCallback = new AsyncCallback(this.OnFileCompletedRead);

                //  set callback for reading of network stream
                callbackRead = new AsyncCallback(this.OnReadComplete);

                //  set callback for writing in network stream
                callbackWrite = new AsyncCallback(this.OnWriteComplete);
            }


            //  start reading string from client
            public void StartRead()
            {
                //  read of network and determine name of file
                networkStream.BeginRead(
                    buffer,
                    0,
                    buffer.Length,
                    callbackRead,
                    null);
            }

            //  show string after reading and send it back to client
            public void OnReadComplete(IAsyncResult asyncResult)
            {
                int bytesRead = networkStream.EndRead(asyncResult);

                //  if a string comes in ...
                if (bytesRead > 0)
                {
                    //  convert string into filename
                    string fileName = Encoding.ASCII.GetString(buffer, 0, bytesRead);

                    //  display status on console
                    Console.Write("Öffne Datei {0}", fileName);

                    //  open stream for file input
                    inputstream = File.OpenRead(fileName);

                    //  start reading file
                    networkStream.BeginRead(
                        buffer,         //  buffer for result
                        0,              //  predefined offset in bytes (0 = no offset)
                        buffer.Length,  //  size of buffer
                        myFileCallback, //  callback delegate
                        null);          //  local object which shows state 
                }
                //  if no string comes in ...
                else
                {   
                    Console.WriteLine("Leseverbindung beendet");    //  display status at console
                    networkStream.Close();                          //  close network stream
                    socket.Close();                                 //  close socket
                    networkStream = null;                          
                    socket = null;
                }
            }

            // if buffer is full with data
            void OnFileCompletedRead(IAsyncResult asyncResult) 
            {
                int bytesRead = inputstream.EndRead(asyncResult);

                //  if something got read from file ...
                if (bytesRead > 0)
                {
                    //  send it to client
                    networkStream.BeginWrite(
                        buffer,
                        0,
                        bytesRead,
                        callbackWrite,
                        null);
                }
                else
                {
                    Console.WriteLine("Ende");
                    networkStream.Close();
                    socket.Close();
                    networkStream = null;
                    socket = null;
                }
            }


            // after successful writing of string begin reading from the start
            private void OnWriteComplete(IAsyncResult asyncResult)
            {
                networkStream.EndWrite(asyncResult);
                Console.WriteLine("Schreiben beendet");

                //  start with reading from file
                networkStream.BeginRead(
                    buffer,         //  Pbuffer for result
                    0,              //  offset
                    buffer.Length,  //  size of buffer
                    myFileCallBack,   //  callback delegate
                    null);          //  local object which show state
            }

        }
        public static void Main()
        {
            AsynchTcpNetworkFileServer serverApplication = new AsynchTcpNetworkFileServer();
            serverApplication.Run();
        }

        private void Run()
        {
            // create new TcpListener and set to receive at Port 60117
            IPAddress localAddr = IPAddress.Parse("127.0.0.1");
            TcpListener tcpListener = new TcpListener(localAddr, 60117);
            tcpListener.Start();

            // continue receiving until the end of file is reached
            for (; ; )
            {
                // accept if client is connecting, return new socket named socketForClient while tcpListener is receiving
                Socket socketForClient = tcpListener.AcceptSocket();
                Console.WriteLine("Client connected");
                ClientHandler handler = new ClientHandler(socketForClient);
                handler.StartRead();
            }            
        }
    }
}


Clientcode
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace Demo_LAMT_TCPClient_3
{
    class AsynchTCPNetworkClient
    {
        private const int bufferSize = 256;
        private NetworkStream streamToServer;

        static public int Main(string[] args)
        {
            AsynchTCPNetworkClient clientApplication = new AsynchTCPNetworkClient();
            return clientApplication.Run(); 
        }

        AsynchTCPNetworkClient()
        {
            string serverName = "localhost";
            Console.WriteLine("Connecting to {0} ...", serverName);
            TcpClient tcpSocket = new TcpClient(serverName, 60117);
            streamToServer = tcpSocket.GetStream();
        }

        private int Run()
        {
            string message = "testFile.txt";
            Console.WriteLine("Sending {0} to server...", message);

            // create StreamWriter for sending string to Server
            StreamWriter writer = new StreamWriter(streamToServer);
            writer.Write(message);
            writer.Flush();

            bool fQuit = false;

            while (!fQuit)
            {   
                //  buffer for response
                char[] responseBuffer = new char[bufferSize];

                //  read response
                StreamReader readerToServer = new StreamReader(streamToServer);

                //  look up how many bytes were read
                int bytesRead = readerToServer.Read(responseBuffer, 0, bufferSize);
                if (bytesRead == 0) //  if no bytes were read
                    fQuit = true;
                else                //  if bytes were read
                {
                    //  Show as string
                    string theString = new String(responseBuffer);
                    Console.WriteLine(theString);
                }
            }
            streamToServer.Close();
            return 0;
        }
    }
}

EDIT: Okay, ich habe einen Fehler gefunden, es macht natürlich keinen Sinn beim Server in Zeile 78 networkStream.BeginRead zu schreiben, das soll inputStream.BeginRead heißen. Nun gibt er mir aus, dass das Schreiben beendet ist, aber es wurde nichts geschrieben, woran kann das liegen?

Edit2: Zeile 134 muss natürlich myFileCallBack heißen. Fehler besteht weiterhin
 
Zuletzt bearbeitet:

rd4eva

Erfahrenes Mitglied
Ehrlich gesagt seh ich da nicht durch.
Du sagst:
Ich habe im Ordner des Programms vom Client eine 16KB große Datei die übertragen werden soll

Wieso wird die testFile.txt dann auf Server Seite eingelesen ?
Servercode->Zeile 75
Code:
inputstream = File.OpenRead(fileName);

Soweit ich das sehen kann ist das einzige was vom client an den Server gesendet wird das hier:
Code:
string message = "testFile.txt";

Und das sollte auch ankommen.
 

s8jascho

Grünschnabel
Oh okay. Ich dachte ich übermittle den Dateinamen vom Client an den Server, öffne die Datei mit gleichem Namen auf der Serverseite und schreibe da dann den Stream rein. Das habe ich wohl nicht so hinbekommen.
Aber so wie du es sagst hast du da wohl Recht, das scheint nicht so zu stimmen und funktioniert daher auch nicht wie gedacht. Jetzt stellt sich mir die Frage wie ich das nun so hinbekomme dass es wie gewünscht funktioniert.
Vielen Dank erstmal, wenn du mir noch einen Tipp geben kannst wäre ich sehr dankbar, ich glaube ich stehe da auch grad auf dem Schlauch.
 

rd4eva

Erfahrenes Mitglied
öffne die Datei mit gleichem Namen auf der Serverseite und schreibe da dann den Stream rein
Ja aber welchen Stream denn? Du sendest ja garnichts.

Der Ablauf sollte doch in etwa folgender sein.
Ich gehe jetzt mal davon aus das der Client eine beliebige Datei an den Server (nicht der gleiche PC) übermitteln muss.
1. Client verbindet sich zum Server
2. Client sendet den Dateinamen an den Server
3. Server erstellt eine Datei mit dem empfangenen Dateinamen
4. Client liest die Datei ein
5. Client sendet den eingelesenen Dateiinhalt an den Server
6. Server empfängt den Dateiinhalt
7. Server schreibt den Dateiinhalt in die unter 3. erstellte Datei.
8. Transfer beendet.
(9. Optional: Server kehrt in den Ursprungszustand zurück um weitere Dateien entgegen nehmen zu können)