C#TCP NetworkStream带有文件流丢失数据

发布于 2025-02-12 08:45:27 字数 2666 浏览 0 评论 0原文

我正在编程一个需要进行文件传输的应用程序。

我应用程序中的大多数通信都是TCP,效果很好。但是,当我尝试进行文件传输时,我似乎在文件的开始和/或结尾失去了一些字节。

这是应该进行文件传输的代码:

Thread sendFile = new Thread(new ThreadStart(() =>
{
    TcpClient tcpClient = new TcpClient(ip, 3);
    tcpClient.Client.DontFragment = true;
    FileStream fileStream = new FileInfo(FilePath).OpenRead();
    Thread.Sleep(1000);
    fileStream.CopyTo(tcpClient.GetStream());
    fileStream.Close();
    tcpClient.Close();
}));
sendFile.SetApartmentState(ApartmentState.STA);
sendFile.Start();
sendFile.Join();

我已经搜索并尝试了通过网络流发送文件流的一系列方法(writeasync,byte [] buffer [buffer,flush the Buffers ,, ...)类似的结果:文件开头的某些字节,每128kb大约消失。

在启动之前,我会以一定的延迟运行传输时,我得到了最好的结果。

客户端代码:

FileStream fileStream = File.Create(path);
Thread receiveFile = new Thread(new ThreadStart(() =>
{
    tcpClient.GetStream().CopyTo(fileStream);
}));
receiveFile.SetApartmentState(ApartmentState.STA);
receiveFile.Start();
receiveFile.Join();
fileStream.Close();

我在与LAN电缆连接的不同计算机和路由器上尝试了它,以确保这些不是问题。

我正在使用.NET Core 5.0

Update

我已经尝试了一些事情,但它使它变得更好,但仍然不完美。

服务器代码:

Thread sendFile = new Thread(new ThreadStart(() =>
{
    TcpClient tcpClient = new TcpClient(ip, 3);
    FileStream fileStream = new FileInfo(FilePath).OpenRead();
    NetworkStream networkStream = tcpClient.GetStream();
    Thread.Sleep(1000);
    byte[] bytes = new byte[1024];
    int read = -1;
    while (read != 0)
    {
        read = fileStream.Read(bytes);
        networkStream.Write(bytes, 0, read);
    }
    filestream.Flush();
    fileStream.Close();
    tcpClient.Close();
}));
sendFile.SetApartmentState(ApartmentState.STA);
sendFile.Start();
sendFile.Join();

客户端代码:

FileStream fileStream = File.Create(path);
BufferedStream networkStream = new BufferedStream(client.GetStream());
Thread receiveFile = new Thread(new ThreadStart(() =>
{
   byte[] bytes = new byte[2048];
   int read = -1;
   while (read != 0)
   {
       read = networkStream.Read(bytes, 0, bytes.Length);
       using (MemoryStream memoryStream = new MemoryStream(bytes))
       {
           using (BinaryReader binaryReader = new BinaryReader(memoryStream))
           {
               fileStream.Write(binaryReader.ReadBytes(read));
           }
       }
   }
fileStream.Flush();
}));
receiveFile.SetApartmentState(ApartmentState.STA);
receiveFile.Start();
receiveFile.Join();
fileStream.Close();

I'm programing an application where I need to make file transfers.

Most of the communication in my application is TCP and works just fine. But when I try to do a file transfer, I seem to lose some bytes at the start and/or end of the file.

Here is the piece of code that is supposed to do the file transfer:

Thread sendFile = new Thread(new ThreadStart(() =>
{
    TcpClient tcpClient = new TcpClient(ip, 3);
    tcpClient.Client.DontFragment = true;
    FileStream fileStream = new FileInfo(FilePath).OpenRead();
    Thread.Sleep(1000);
    fileStream.CopyTo(tcpClient.GetStream());
    fileStream.Close();
    tcpClient.Close();
}));
sendFile.SetApartmentState(ApartmentState.STA);
sendFile.Start();
sendFile.Join();

I have searched and tried a bunch of methodes of sending a filestream through a networkstream (WriteAsync, byte[] buffer, flushing the buffers,...) but all had similar results: some bytes at the start of the file and about every 128kb disappear.

I got the best results when running the transfer in a STA thread with some delay before starting.

Client code:

FileStream fileStream = File.Create(path);
Thread receiveFile = new Thread(new ThreadStart(() =>
{
    tcpClient.GetStream().CopyTo(fileStream);
}));
receiveFile.SetApartmentState(ApartmentState.STA);
receiveFile.Start();
receiveFile.Join();
fileStream.Close();

I tried it on different computers and routers connected with LAN cables to make sure those weren't the problems.

I'm using .Net Core 5.0

Update

I've tried a few things and it made it better, but still not perfect.

Server code:

Thread sendFile = new Thread(new ThreadStart(() =>
{
    TcpClient tcpClient = new TcpClient(ip, 3);
    FileStream fileStream = new FileInfo(FilePath).OpenRead();
    NetworkStream networkStream = tcpClient.GetStream();
    Thread.Sleep(1000);
    byte[] bytes = new byte[1024];
    int read = -1;
    while (read != 0)
    {
        read = fileStream.Read(bytes);
        networkStream.Write(bytes, 0, read);
    }
    filestream.Flush();
    fileStream.Close();
    tcpClient.Close();
}));
sendFile.SetApartmentState(ApartmentState.STA);
sendFile.Start();
sendFile.Join();

Client code:

FileStream fileStream = File.Create(path);
BufferedStream networkStream = new BufferedStream(client.GetStream());
Thread receiveFile = new Thread(new ThreadStart(() =>
{
   byte[] bytes = new byte[2048];
   int read = -1;
   while (read != 0)
   {
       read = networkStream.Read(bytes, 0, bytes.Length);
       using (MemoryStream memoryStream = new MemoryStream(bytes))
       {
           using (BinaryReader binaryReader = new BinaryReader(memoryStream))
           {
               fileStream.Write(binaryReader.ReadBytes(read));
           }
       }
   }
fileStream.Flush();
}));
receiveFile.SetApartmentState(ApartmentState.STA);
receiveFile.Start();
receiveFile.Join();
fileStream.Close();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

允世 2025-02-19 08:45:27

正如我认为问题所在的TCPCLIENT上。使用普通插座时,一切都应该按应有的作用:没有数据丢失。

客户端代码:

Thread receiveFile = new Thread(new ThreadStart(() =>
{
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
    socket.Bind(new IPEndPoint(IPAddress.Any, 33));
    socket.Listen();
    socket = socket.Accept();
    FileStream fileStream = File.Create(path);
    NetworkStream networkStream = new NetworkStream(socket);
    networkStream.CopyTo(fileStream);
    fileStream.Flush();
    fileStream.Close();
    socket.Close();
    socket.Dispose();
}));
receiveFile.SetApartmentState(ApartmentState.STA);
receiveFile.Start();
receiveFile.Join();
GC.Collect();

服务器代码:

Thread sendFile = new Thread(new ThreadStart(() =>
{
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
    socket.Connect(new IPEndPoint(IPAddress.Parse(client.Host), 33));
    FileStream fileStream = new FileInfo(FilePath).OpenRead();
    NetworkStream networkStream = new NetworkStream(socket);
    Thread.Sleep(1000);
    fileStream.CopyTo(networkStream);
    fileStream.Flush();
    fileStream.Close();
    socket.Close();
    socket.Dispose();
}));
sendFile.SetApartmentState(ApartmentState.STA);
sendFile.Start();
sendFile.Join();
GC.Collect();

我强迫收集器确保插座处置,因此可以再次使用它们。

As I had assumed the problem lies on the TcpClient. When using normal sockets everything works as it should: no data loss.

Client code:

Thread receiveFile = new Thread(new ThreadStart(() =>
{
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
    socket.Bind(new IPEndPoint(IPAddress.Any, 33));
    socket.Listen();
    socket = socket.Accept();
    FileStream fileStream = File.Create(path);
    NetworkStream networkStream = new NetworkStream(socket);
    networkStream.CopyTo(fileStream);
    fileStream.Flush();
    fileStream.Close();
    socket.Close();
    socket.Dispose();
}));
receiveFile.SetApartmentState(ApartmentState.STA);
receiveFile.Start();
receiveFile.Join();
GC.Collect();

Server code:

Thread sendFile = new Thread(new ThreadStart(() =>
{
    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
    socket.Connect(new IPEndPoint(IPAddress.Parse(client.Host), 33));
    FileStream fileStream = new FileInfo(FilePath).OpenRead();
    NetworkStream networkStream = new NetworkStream(socket);
    Thread.Sleep(1000);
    fileStream.CopyTo(networkStream);
    fileStream.Flush();
    fileStream.Close();
    socket.Close();
    socket.Dispose();
}));
sendFile.SetApartmentState(ApartmentState.STA);
sendFile.Start();
sendFile.Join();
GC.Collect();

I forced the collector to make sure the sockets are disposed, so they can be used again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文