【问题标题】:How to send file more then once如何发送文件不止一次
【发布时间】:2018-05-24 23:16:55
【问题描述】:

有两个 C# 项目:一个项目用于客户端,另一个项目用于服务器。第一步是运行服务器,然后选择一个目标文件夹,然后运行客户端项目,选择一些 text.txt 发送到服务器的目标文件夹。 只有客户端可以向服务器发送文件

演示:

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

这很好用,但我希望它每隔几分钟自动发送一次 text.txt,所以我添加了while(true) 循环和Thread.Sleep(10000),但它总是给出异常。我的意思是,它不会让我多发送一次。

我正在尝试在客户端类中放置一个 while 循环:

 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....";
            }
        }

服务器类:

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

【问题讨论】:

  • 这个问题可以解释为“我编写了一个运行在TCP之上的应用协议。请帮我检查协议,提及任何设计错误并指出我的实现中的错误导致我无法通过一个连接发送两个文件”。请阅读How to Ask 了解为什么这不是本网站的运作方式。无论如何,请阅读NetworkStream.Close() 的文档。
  • @mjwills System.ObjectDisposedException上线s.Write(b1, 0, b1.Length);

标签: c# tcp-ip


【解决方案1】:

尝试更改为:

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 语句有助于处理对象。

或者,如果您想保持连接打开,请尝试:

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,我不得不对你投反对票,因为“使用”在声明后立即处理 Client 和 StreamWriter。您应该添加括号。编辑代码,我将删除downvote
  • @Anderson,每 18 秒重新连接一次也不是很有效,如果您知道文件将每 18 秒发送一次,您不妨保持连接打开。
  • @JuanTheron 你错了。这是using-s 嵌套的流行语法 - 除了最里面的using 之外,您可以省略所有括号。因为using作用域是它的声明区和下一条语句(也就是下一个using块)。
  • 以这个问题和答案(stackoverflow.com/q/23197606/1094048)为例
  • 你现在可以在线使用它;)查看我的示例(dotnetfiddle.net/7CgGbm
【解决方案2】:

好的,这是你的问题:

在第一个循环中,它按预期工作正常,因为一切都已正确初始化,但在发送第一个文件后,您调用 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);
}

现在发生的情况是在第一个循环之后关闭流,然后在第二个循环中它已经“释放”。

修复移动 s.Close();跳出循环并进入断开按钮事件或应用程序关闭事件。

另外我建议不要使用 Thread.Sleep(interval); 这是因为 sleep 会冻结您的线程,而 .NET 中的主线程用于您的界面,因此冻结该线程非常糟糕。

像以前的帖子一样创建一个新线程:

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();
}

并记住对该线程使用try catch块,否则如果发生异常,将无法很好地处理。另请记住,在此线程运行时关闭应用程序将使您的应用程序保持打开状态,直到您手动终止该进程,因此在应用程序关闭事件中记得终止线程。

而且 close 正在发送一个信号让线程退出,但它可能需要长达 18 秒才能完全退出,另一种解决方案是使用 thread.Abort();但这是一个肮脏的出口,它很可能会引发异常。

再次记住阅读线程,这是一个快速但糟糕的版本,它应该是在生产环境中的样子。

【讨论】:

  • 应该是,我看不出有什么问题。只要记住 using 语句,否则它将是: System.Threading.Thread thread = new System.Threading.Thread(sendFile);
  • @Error 404,请将问题标记为已接受,因为它解决了您最初的异常:“System.ObjectDisposedException”。然后为服务器端代码开新帖
猜你喜欢
  • 2017-02-22
  • 2014-07-27
  • 1970-01-01
  • 2020-04-23
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多