Breakpoint affects the result during TCP send

I have a problem with a Client / Server application I am writing. The goal is to send specific directory files to the Client and send them to a directory on the Server.

I get files with foreach, but when I put a breakpoint at the beginning of foreach, and continue until I send all the files, I get all of them on my server as I want, when I remove the breakpoint and restart my application, my server just gets part of the files and I don't know why.

I'm not sure, but I suppose this is a threading issue, but I don't know how to solve it.

Server:

static void Main(string[] args)
{
     try
      {

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

            // Start listening
            listen.Start();

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


            StreamReader reader = new StreamReader(client.GetStream());

            netStream = client.GetStream();
            string fileName;
            bool endOfSend=false;
           do
            {
                fileName = reader.ReadLine();

                // 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;

                    }                  

                allBytesRead = 0;
                bytesLeft = 0;
                bytesRead = 0;

                // Save file to desktop
                Console.WriteLine("File {0} received.", fileName);
                File.WriteAllBytes(@"C:\Users\toto2\Desktop\" + fileName, data);

            } while (!endOfSend);
            netStream.Close();
            client.Close();
            Console.ReadLine();
        }
        catch (Exception ex)
        {
            Console.WriteLine("File Receiving fail." + ex.Message);
        }
    }

      

Customer:

static void Main(string[] args)
{
try
{
    IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
    int port = 3003;

    TcpClient client = new TcpClient();
    //NetworkStream netStream;

    // Connect to server
    try
    {
        client.Connect(new IPEndPoint(ipAddress, port));
        Console.WriteLine("Connecté.....");
        SendFiles(client);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    // Clean up
    client.Close();
    Console.Read();
}
catch (Exception ex)
{
    Console.WriteLine("File Sending fail." + ex.Message);
}


}

public static  void SendFiles(TcpClient cli) {
    NetworkStream netS=cli.GetStream();

   int bufferSize = 1024;
    string[] files = Directory.GetFiles(@"C:\Users\toto\Mes Images\test");


StreamWriter writer = new StreamWriter(cli.GetStream());


foreach (string item in files)
{
    writer.WriteLine(Path.GetFileName(item));
    writer.Flush();


    // Read bytes from image
    byte[] data = File.ReadAllBytes(Path.GetFullPath(item));

    // 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;

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

    }
}
writer.Close();
netS.Close();
}

      

Thanks, someone will try to help me.

+3


source to share


2 answers


You might want to implement and confirm from the server to the client that it received 1 file. Then ask the client to send the next file. As far as I can tell, you are just sending all files at once. Below is a simple confirmation implementation. You should be able to use the appropriate parts for your script.



//
/*   Server Program    */

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;

public class serv {
    public static void Main() {
    try {
        IPAddress ipAd = IPAddress.Parse("172.21.5.99");
         // use local m/c IP address, and 
         // use the same in the client

/* Initializes the Listener */
        TcpListener myList=new TcpListener(ipAd,8001);

/* Start Listeneting at the specified port */        
        myList.Start();

        Console.WriteLine("The server is running at port 8001...");    
        Console.WriteLine("The local End point is  :" + 
                          myList.LocalEndpoint );
        Console.WriteLine("Waiting for a connection.....");

        Socket s=myList.AcceptSocket();
        Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);

        byte[] b=new byte[100];
        int k=s.Receive(b);
        Console.WriteLine("Recieved...");
        for (int i=0;i<k;i++)
            Console.Write(Convert.ToChar(b[i]));

        ASCIIEncoding asen=new ASCIIEncoding();
        s.Send(asen.GetBytes("The string was recieved by the server."));
        Console.WriteLine("\nSent Acknowledgement");
/* clean up */            
        s.Close();
        myList.Stop();

    }
    catch (Exception e) {
        Console.WriteLine("Error..... " + e.StackTrace);
    }    
    }

}

---------------------------------------------------------------------------

/*       Client Program      */

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;


public class clnt {

    public static void Main() {

        try {
            TcpClient tcpclnt = new TcpClient();
            Console.WriteLine("Connecting.....");

            tcpclnt.Connect("172.21.5.99",8001);
            // use the ipaddress as in the server program

            Console.WriteLine("Connected");
            Console.Write("Enter the string to be transmitted : ");

            String str=Console.ReadLine();
            Stream stm = tcpclnt.GetStream();

            ASCIIEncoding asen= new ASCIIEncoding();
            byte[] ba=asen.GetBytes(str);
            Console.WriteLine("Transmitting.....");

            stm.Write(ba,0,ba.Length);

            byte[] bb=new byte[100];
            int k=stm.Read(bb,0,100);

            for (int i=0;i<k;i++)
                Console.Write(Convert.ToChar(bb[i]));

            tcpclnt.Close();
        }

        catch (Exception e) {
            Console.WriteLine("Error..... " + e.StackTrace);
        }
    }

}

      

+1


source


You have a hybrid binary / text protocol. It can be painful. StreamReader

buffers parts of the stream. It takes more than it returns immediately as a string. You cannot mix it with other readers.

Throw away all this code and use a higher level communication mechanism. For example WCF with MTOM for binary streaming. Or HTTP.



If you don't want to use BinaryReader

ad BinaryWriter

. They are quite easy to use.

Note that when reading the length, you are assuming that all 4 bytes will arrive in one read. This assumption is incorrect.

+1


source







All Articles