c# - Stream.Read 正在组合两个不同的读取

标签 c# client client-server filestream

我有一个用 C# 编写的简单文件服务器\客户端应用程序。但我经常遇到这样的问题:我的流将两个不同的读取写入单个缓冲区。我有一个同步流,但仍然没有帮助。有什么建议么?谢谢!

System.Threading.Thread.Sleep(25);
receive_fspos = new byte[30];
int bytesread = stream_1.Read(receive_fspos, 0, receive_fspos.Length);//this is where it gets combined
if (bytesread == 0) 
{ 
    finished = true; 
    System.Threading.Thread.Sleep(25); 
}
string string_1 = utf.GetString(receive_fspos).TrimEnd(new char[] { (char)0 });
int fsposition = (int)Convert.ToInt64(string_1);
bytestosend = fsposition;
filestream.Position = fsposition;
byte[] buffer_1 = new byte[bufsize];
int bytesreadfromfs = filestream.Read(buffer_1, 0, buffer_1.Length);
stream_1.Write(buffer_1, 0, buffer_1.Length);
Console.Write("\rSent " + fsposition + " / " + length + " bytes");
finished = true;

最佳答案

如果您不完全理解它,我不建议您编写自己的流方法。

您遇到的问题是因为传入的数据是字节流,它无法让您知道消息的长度有多少字节。

在下面的代码中,您声明您想要读取流的“receive_fspos.Length”字节。由于“receive_fspos.Length”为 30,因此将读取的字节数将在 0 到 30 之间。

如果连接仅接收到 15 个字节。它会给你 15 个字节。如果消息的长度是 20 个字节。然后消息现在被分成不同的段。

如果第一条消息是 4 字节,第二条消息是 12 字节。现在您有 2 条消息,末尾有一组 16 个空白字节。更糟糕的是,这 16 个“空白”字节可能是进入流的第三条消息的开始。

如果消息长度为 50 字节。那么你只会收到一半的消息。现在您需要将读取的字节添加到单独的缓冲区中。再次从流中读取。然后重复此操作,直到确定已读取完成整个消息所需的确切字节数。然后将所有读取的字节连接回单个字节[]。

     receive_fspos = new byte[30];
     int bytesread = stream_1.Read(receive_fspos, 0, receive_fspos.Length);//this is where it gets combined

请使用 BCL 方法,而不是滚动自己的循环。听起来你正在使用字符串,所以这将是首选方法..我建议如下。

using(NetworkStream networkStream = tcpClient.GetStream())
using(StreamReader streamReader = new StreamReader(networkStream))
using(StreamWriter streamWriter = new StreamWriter(networkStream))
{
     networkStream.ReadTimeout = timeout; //Set a timeout to stop the stream from reading indefinately           

     //To receive a string
     string incomingString = stream.ReadLine();

     //To send a string
     stream.WriteLine(messageToSend);
     stream.Flush();
}

您的回答表明您正在尝试发送文件。为此,我建议发送一个字节数组[]。使用此方法,您可以发送任何可以序列化的内容。这包括一个文件。请注意,文件的大小是有限的,因为它必须保存在内存中。要写入更大的文件,您需要在数据流入时以 block 的形式保存数据。

//Please note that if the file size is large enough. It may be preferred to use a stream instead of holding the entire file in memory.
byte[] fileAsBytes = File.ReadAllBytes(fileName);

using(NetworkStream networkStream = tcpClient.GetStream())
using(BinaryReader binaryReader = new BinaryReader(networkStream))
using(BinaryWriter binaryWriter = new BinaryWriter(networkStream))
{
     networkStream.ReadTimeout = timeout; //Set a timeout to stop the stream from reading indefinately           

     //To receive a byte array
     int incomingBytesLength = BinaryReader.ReadInt32(); //The header is 4 bytes that lets us know how large the incoming byte[] is.
     byte[] incomingBytes = BinaryReader.ReadBytes(incomingBytesLength);

     //To send a byte array
     BinaryWriter.Write(fileAsBytes.Length); //Send a header of 4 bytes that lets the listener know how large the incoming byte[] is.
     BinaryWriter.Write(fileAsBytes);
}

关于c# - Stream.Read 正在组合两个不同的读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15036790/

相关文章:

android - 移动网络性能 : What would be the most efficient data-type to transfer data from a webserver to a mobilephone?

javascript - GWT 服务器,在客户端构建 get() 和 post()

c# - Active Directory 中的 userAccountControl

java - 自定义 XML 消息上带有 Java Socket 服务器的 WCF TCP 客户端

c# - 更改 DateTime 的时区以满足 API 契约(Contract)

c++ - sendto 和 recvfrom 在同一个程序中?

java - Netty - 如何最好地为具有大量 POJO 的桌面应用程序构建客户端/服务器

c - C linux 中的信号量与客户端/服务器

c# - C#中的树节点选择问题

c# - 为什么数组大小声明使用 "1"作为第一个索引?