-2

There are two C# projects: one project is for the client, the other one is for the server. First step is to run the server , then to choose a target folder, after that to run the client project, to choose some text.txt to send to the server's target folder. Only client can send files to the server

Demo:

1.choosing file target                       2.client sends
   +------------+                                
   | tar folder |          <----------------       text.txt 
   +------------+

This works fine, but I want it to send the text.txt automatically every few minutes so I added while(true) loop and Thread.Sleep(10000) but it alaway gives Exceptions. I mean, It's not gives me to send it more then once.

Here the in client class I'm trying to put a while loop :

 public Form1()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)//browse btn
        {
            string n;
            byte[] b1;
            TcpClient client;
            OpenFileDialog op;
            Stream s;
            StreamWriter sw;
            op = new OpenFileDialog();

            if (op.ShowDialog() == DialogResult.OK)
            {
                string t = textBox1.Text;
                t = op.FileName;
                FileInfo fi = new FileInfo(textBox1.Text = op.FileName);
                n = fi.Name + "." + fi.Length;

                client = new TcpClient("127.0.0.1", 8100);//"127.0.0.1", 5055

                sw = new StreamWriter(client.GetStream());
                s = client.GetStream();
                b1 = File.ReadAllBytes(op.FileName);

                //  s = client.GetStream();
                while (true)
                {

                    s.Write(b1, 0, b1.Length);
                    sw.WriteLine(n);
                     sw.Flush();
                    //sw.Close();
                    s.Close();//added by me
 Thread.Sleep(18000);

                                   }
                sw.Flush();
                client.Close();

                // label2.Text = "File Transferred....";
            }
        }

Server class:

public Form1()
        {
            InitializeComponent();
        }

        string rd;
        byte[] b1;
        string v;
        int m=20;//number of byts
        TcpListener list;
        TcpClient client;
        int port = 8100;//5050
        int port1 = 8100;//5055
        IPAddress localAddr = IPAddress.Parse("127.0.0.1");
        private void button1_Click(object sender, EventArgs e)//browse button
        {

            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {

                    textBox1.Text = folderBrowserDialog1.SelectedPath;
                    list = new TcpListener(localAddr, port1);
                    list.Start();

                    Thread incoming_connection = new Thread(ic);
                    incoming_connection.Start();

            }
        }

        private void ic()
        {

            client = list.AcceptTcpClient();
            Stream s = client.GetStream();
            b1 = new byte[m];
            s.Read(b1,0, b1.Length);
            MessageBox.Show("pathh "+textBox1.Text);
            File.WriteAllBytes(textBox1.Text+"\\flag.txt", b1);// the left side us the name of the written file
            //list.Stop();
            //client.Close();
          //  label1.Text = "File Received......";
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            list = new TcpListener(localAddr, port);
           // TcpListener list = new TcpListener(port);
            list.Start();
            TcpClient client = list.AcceptTcpClient();
            MessageBox.Show("Client trying to connect");
            StreamReader sr = new StreamReader(client.GetStream());
            rd = sr.ReadLine();
            v = rd.Substring(rd.LastIndexOf('.') + 1);
            m = int.Parse(v);
           // list.Stop();
           // client.Close();
        }

Related

Error 404
  • 427
  • 5
  • 25
  • 4
    This question could be interpreted as _"I made up an application protocol running on top of TCP. Please review the protocol for me, mention any design mistakes and also point out mistakes in my implementation causing me to be unable to send two files over one connection"_. Please read [ask] to see why that isn't how this site works. Anyway, read the docs for [`NetworkStream.Close()`](https://msdn.microsoft.com/en-us/library/system.io.stream.close(v=vs.110).aspx). – CodeCaster Dec 11 '17 at 12:21
  • @mjwills `System.ObjectDisposedException` on the line `s.Write(b1, 0, b1.Length);` – Error 404 Dec 11 '17 at 12:24

2 Answers2

1

Try changing to:

while (true)
{
    using (var client = new TcpClient("127.0.0.1", 8100))//"127.0.0.1", 5055
    using (var sw = new StreamWriter(client.GetStream()))
    using (var s = client.GetStream())
    {
        b1 = File.ReadAllBytes(op.FileName);
        //  s = client.GetStream();
        s.Write(b1, 0, b1.Length);
        sw.WriteLine(n);
        sw.Flush();
    }
    Thread.Sleep(18000);
}

using statement helps on disposing objects.

Alternativelly, if you want to keep the connection open, try:

using (var client = new TcpClient("127.0.0.1", 8100))//"127.0.0.1", 5055
while (true)
{
    using (var sw = new StreamWriter(client.GetStream()))
    using (var s = client.GetStream())
    {
        b1 = File.ReadAllBytes(op.FileName);
        //  s = client.GetStream();
        s.Write(b1, 0, b1.Length);
        sw.WriteLine(n);
        sw.Flush();
    }
    Thread.Sleep(18000);
}
Anderson Pimentel
  • 5,086
  • 2
  • 32
  • 54
  • @Anderson, I had to downvote you because the 'using' is disposing the Client and StreamWriter immiately after its declared. You should have added brackets. Edit the code and I will remove the downvote – Kickass Dec 11 '17 at 13:55
  • @Anderson, also it's *NOT* very effiecient to reconnect every 18 seconds, if you know the file is going to be sent every 18 seconds, you might as well keep the connection open. – Kickass Dec 11 '17 at 13:58
  • 3
    @JuanTheron you're wrong. It's popular syntax for `using`-s nesting - you can omit all brackets except for innermost `using`. Because `using` scope is its declaration area and the next statement (which is next `using` block). – pkuderov Dec 11 '17 at 14:16
  • Look at this question and the answer (https://stackoverflow.com/q/23197606/1094048) for example – pkuderov Dec 11 '17 at 14:18
  • Ok I hear you, I have never seen it being used like this and I can't be sure because I dont have a compiler for .NET or Windows right now so I can't test it but what your saying makes sense. – Kickass Dec 11 '17 at 14:20
  • 1
    you can use it online nowadays ;) check my example (https://dotnetfiddle.net/7CgGbm) – pkuderov Dec 11 '17 at 14:32
  • @JuanTheron It's like an `if` statement: if it has only one line, you don't need the brackets. – Anderson Pimentel Dec 11 '17 at 15:13
  • @AndersonPimentel I tried both, for the second one: this gives exception on line `using (var sw = new StreamWriter(client.GetStream())) ` the exceprion is: `System.InvalidOperationException:` – Error 404 Dec 11 '17 at 15:49
  • @Anderson Yeah no I know that rule, It's just hard to keep track of which languages takes a new line as a terminator. The ; is a dead give away ;) – Kickass Dec 11 '17 at 16:10
  • @Error 404 - This is a quote from MSDN: "The exception that is thrown when a method call is invalid for the object's current state." https://msdn.microsoft.com/en-us/library/system.invalidoperationexception(v=vs.110).aspx Which means it's probably due to the client not not being connected yet...Add a try catch statement – Kickass Dec 11 '17 at 16:11
  • @JuanTheron I will add the server class also, I think I should add a while loop that the server will continue to listen all the time for more files – Error 404 Dec 11 '17 at 16:14
1

Ok here is your problem:

On the first loop it works fine as expected because everything is initialized correctly but then after it sends the first file you call s.Close();

while (true)
{
s.Write(b1, 0, b1.Length);
sw.WriteLine(n);
sw.Flush();
//sw.Close();
s.Close();//added by me
Thread.Sleep(18000);
}

Now what happens is after the first loop you close the stream and then on the second loop it is already 'Disposed'.

To fix move the s.Close(); out of the loop and into a disconnect button event or the application close event.

Also I would advise against using Thread.Sleep(interval); This is because sleep freezes your thread and the main thread in .NET is used for your interface so freezing that thread is very bad.

Create a new thread like in previous post:

using System.Threading;

Stream s;
byte[] b1;
TcpClient client;
OpenFileDialog op;
StreamWriter sw;
Thread thread = new Thread(sendFile);
string fn;
string n;
threadExit = false;
Int32 interval = 18000;

public Form1()
{
  InitializeComponent();
}
private void Form1_OnLoad(object sender,EventArgs e) {
  op = new OpenFileDialog();
  client = new TcpClient("127.0.0.1", 8100);//"127.0.0.1", 5055
  sw = new StreamWriter(client.GetStream());
  s = client.GetStream();
  //It would be your responsibility to move this code to the proper place
  //because now it tries to open the connection when your app loads
}
private void sendFile() {
  while (!threadExit)
  {
    b1 = File.ReadAllBytes(fn);
    s.Write(b1, 0, b1.Length);
    sw.WriteLine(n);
    sw.Flush();
    Thread.Sleep(interval);
  }
}

private void button1_Click(object sender, EventArgs e)
{
  if (op.ShowDialog() == DialogResult.OK)
  {
    fn = op.FileName;
    FileInfo fi = new FileInfo(textBox1.Text = op.FileName);
    n = fi.Name + "." + fi.Length;
    thread.Start();
  }
  //It would be a good idea to add an indicator to signal that another thread is trying to send the file at a set interval

}
private void Form1_Close(object sender, EventArgs e) {
  s.Close();
  client.Close();
  threadExit = true;
  Application.Exit();
}

And remember to use try catch blocks for this thread otherwise if an exception occurs it wont be handled very good. Also keep in mind that closing the app while this thread is running WILL keep your app open until you manually kill the process, so on the app close event remember to kill the thread.

And also the close is sending a signal for the thread to exit but it can take up to 18 seconds to exit cleanly, another solution is to use thread.Abort(); but thats a dirty exit and it will most likely throw an exception.

And once again rememeber to read up on threading, this is a fast, and BAD, version of how it's supposed to be in a production environment.

Kickass
  • 1,114
  • 9
  • 16
  • Should be, I don't see anything wrong with it. Just remember the using statement otherwise it will be: System.Threading.Thread thread = new System.Threading.Thread(sendFile); – Kickass Dec 11 '17 at 16:15
  • @Error 404, please mark the question as accepted because it solved your original exception of: "System.ObjectDisposedException". Then open a new post for the server-side code – Kickass Dec 11 '17 at 16:22