gpt4 book ai didi

c# - 使用 NetworkStream 接收文件随机失败,但始终适用于 Thread.Sleep()

转载 作者:可可西里 更新时间:2023-11-01 02:41:06 24 4
gpt4 key购买 nike

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

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

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

虽然这个 hack 似乎解决了这个问题,但我对此并不满意,因为我并不真正理解它为什么起作用,现在我正在寻找一个更清洁/更强大的解决方案来解决这个问题。

这是我的代码:

服务器:

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

客户:

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

}

}
}

如有任何帮助,我们将不胜感激!

最佳答案

您正在直接使用流进行混合,并通过 StreamReader 读取它。 StreamReader 可以缓冲读取。即:它可以从文件中读取比您预期更多的内容。这意味着底层 Stream 的读取位置可以超出您的想象。

(Sleep 可能导致 StreamReader 在读取期间超时,并发现它拥有所需的一切。因此它返回时没有将流推进到第一个之后线)

要么不使用阅读器直接从底层流读取,要么始终使用阅读器读取。在这种情况下,您最好使用 BinaryReader,因为无论如何您都想读取二进制文件。

关于c# - 使用 NetworkStream 接收文件随机失败,但始终适用于 Thread.Sleep(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20377730/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com