C# 使用NetworkStream接收文件会随机失败,但始终与Thread.Sleep()配合使用

C# 使用NetworkStream接收文件会随机失败,但始终与Thread.Sleep()配合使用,c#,sockets,tcp,network-programming,tcpclient,C#,Sockets,Tcp,Network Programming,Tcpclient,我是网络编程新手,我正在尝试使用NetworkStream(C#)将文件从客户端发送到服务器 我认为下面的代码应该可以工作,但有时(随机)接收端(服务器)将永远循环,文件将不会被接收(发送似乎工作正常) 我让一位助手在学校查看了代码,他提出了以下修复/破解方法:在进入发送文件的循环之前使用Thread.Sleep(500)。但是他没有向我解释为什么会这样,他只是说这是会发生的事情,并且原始代码(没有Thread.Sleep(500))应该可以正常工作(有时确实如此) 虽然这个黑客似乎解决了这个问

我是网络编程新手,我正在尝试使用NetworkStream(C#)将文件从客户端发送到服务器

我认为下面的代码应该可以工作,但有时(随机)接收端(服务器)将永远循环,文件将不会被接收(发送似乎工作正常)

我让一位助手在学校查看了代码,他提出了以下修复/破解方法:在进入发送文件的循环之前使用Thread.Sleep(500)。但是他没有向我解释为什么会这样,他只是说这是会发生的事情,并且原始代码(没有Thread.Sleep(500))应该可以正常工作(有时确实如此)

虽然这个黑客似乎解决了这个问题,但我对它不满意,因为我真的不明白它为什么会起作用,现在我正在寻找一个更干净/更健壮的解决方案来解决这个问题

这是我的密码:

服务器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace _003
{
    class server
    {
        [STAThread]
        static void Main(string[] args)
        {
            //args = ip, port
            try
            {
                TcpListener myTcpListener = new TcpListener(IPAddress.Parse(args[0]), int.Parse(args[1]));
                myTcpListener.Start();
                Socket sejaSocket;

                while (true)
                {
                    //čakamo na povezavo iz clienta
                    sejaSocket = myTcpListener.AcceptSocket();
                    if (sejaSocket.Connected)
                    {
                        NetworkStream stream = new NetworkStream(sejaSocket);
                        StreamWriter sWriter = new StreamWriter(stream);
                        sWriter.AutoFlush = true;
                        StreamReader sReader = new StreamReader(stream);

                        FileStream myFileStream = new FileStream(@"output.file", FileMode.Create, FileAccess.Write);
                        long rdby = 0;
                        int len;
                        byte[] buffed = new byte[1024];

                        Console.WriteLine("Prejemam datoteko!");

                        int dolzinaDat = int.Parse(sReader.ReadLine());

                        while (rdby < dolzinaDat)
                        {
                            Console.Write("#");

                            len = stream.Read(buffed, 0, buffed.Length);
                            myFileStream.Write(buffed, 0, len);
                            myFileStream.Flush();
                            rdby += len;

                            Console.WriteLine(dolzinaDat + " " + rdby + " " + len.ToString());
                        };

                        stream.Close();
                        myFileStream.Close();

                        Console.WriteLine();
                        Console.WriteLine("Prenos končan!");
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
Net系统;
使用System.Net.Sockets;
使用系统线程;
使用System.IO;
名称空间_003
{
类服务器
{
[状态线程]
静态void Main(字符串[]参数)
{
//args=ip,端口
尝试
{
TcpListener myTcpListener=新的TcpListener(IPAddress.Parse(args[0]),int.Parse(args[1]);
myTcpListener.Start();
插座插座;
while(true)
{
//čakamo na povezavo iz clienta
sejaSocket=myTcpListener.AcceptSocket();
如果(sejaSocket.Connected)
{
NetworkStream=新的NetworkStream(sejaSocket);
StreamWriter sWriter=新StreamWriter(流);
sWriter.AutoFlush=true;
StreamReader sReader=新的StreamReader(流);
FileStream myFileStream=newfilestream(@“output.file”、FileMode.Create、FileAccess.Write);
长rdby=0;
内伦;
字节[]缓冲=新字节[1024];
控制台。WriteLine(“Prejemam datoteko!”);
int-dolzinaDat=int.Parse(sReader.ReadLine());
while(rdby
客户:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;

namespace _003
{
    class client
    {
        [STAThread]
        static void Main(string[] args)
        {
            //args = ip, port
            try
            {
                TcpClient sejaTcpClient = new TcpClient();
                sejaTcpClient.Connect(IPAddress.Parse(args[0]), int.Parse(args[1]));

                NetworkStream stream = sejaTcpClient.GetStream();
                StreamWriter sWriter = new StreamWriter(stream);
                sWriter.AutoFlush = true;
                StreamReader sReader = new StreamReader(stream);

                FileStream myFileStream = new FileStream(@"input.file", FileMode.Open, FileAccess.Read);
                long rdby = 0;
                int len;
                byte[] buffed = new byte[1024];

                Console.WriteLine("Pošiljam datoteko!");

                long dolzinaDat = myFileStream.Length;
                sWriter.WriteLine(dolzinaDat);

                //UNCOMMENT THIS AND THE CODE WORKS FINE
                //Thread.Sleep(500);

                while (rdby < dolzinaDat)
                {
                    Console.Write("#");

                    len = myFileStream.Read(buffed, 0, buffed.Length);
                    stream.Write(buffed, 0, len);
                    stream.Flush();
                    rdby += len;

                    Console.WriteLine(dolzinaDat + " " + rdby + " " + len.ToString());
                }

                stream.Close();
                myFileStream.Close();

                Console.WriteLine();
                Console.WriteLine("Prenos končan!");

                Console.WriteLine("Pritisni tipko, da končas");
                Console.ReadKey(true);
                Console.WriteLine("Konec");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

        }

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
Net系统;
使用System.Net.Sockets;
使用系统线程;
使用System.IO;
名称空间_003
{
类客户端
{
[状态线程]
静态void Main(字符串[]参数)
{
//args=ip,端口
尝试
{
TcpClient sejaTcpClient=新的TcpClient();
sejaTcpClient.Connect(IPAddress.Parse(args[0])、int.Parse(args[1]);
NetworkStream=sejaTcpClient.GetStream();
StreamWriter sWriter=新StreamWriter(流);
sWriter.AutoFlush=true;
StreamReader sReader=新的StreamReader(流);
FileStream myFileStream=newfilestream(@“input.file”、FileMode.Open、FileAccess.Read);
长rdby=0;
内伦;
字节[]缓冲=新字节[1024];
Console.WriteLine(“Pošiljam datoteko!”);
long dolzinaDat=myFileStream.Length;
斯维特·瑞特琳(多吉纳达);
//取消对此的注释,代码就可以正常工作
//睡眠(500);
while(rdby

任何帮助都将不胜感激

在发送内容之前,您正在将文件长度作为新行写入。但是,StreamReader.ReadLine可以从流中读取比单行多的字节。这是因为它执行内部缓冲。要准确地读取单行,它必须从流中读取单个字节,这是一个效率噩梦


使用BinaryReader/Writer将文件长度作为
long

直接使用流进行混合,并通过
StreamReader
读取。
StreamReader
可以缓冲读取。也就是说:它可以从文件中读取比您预期的更多的内容。这意味着基础
Str