- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
NetworkStream 从套接字缓冲区读取不应该存在的数据时出现问题。顺便说一句,我正在发送非常大的缓冲区。现在我刚刚在本地主机上进行测试。
这是我读取数据的方式,前 4 个字节包含消息的长度,然后我只读取 4096 个 block ,直到达到消息的长度。
protected TcpClient tcpObject;
protected NetworkStream tcpStream;
private void HandleComm()
{
try
{
tcpStream = tcpObject.GetStream();
byte[] totalByteAray = new byte[constIntSize];
byte[] message = new byte[constChunkSize];
byte[] fullMessage = new byte[0];
//this is how many bytes long the message will be
int totalBytes = 0;
int currentBytes = 0;
int chunkSize = constChunkSize;
while (true)
{
//skip reading if no data is available
//DataAvailable does not tell you when all the data has arrived
//it just tell you if some data has arrived
if (tcpStream.CanRead)
{
totalBytes = 0;
currentBytes = 0;
message = new byte[constChunkSize];
chunkSize = constChunkSize;
//The first 4 bytes of the message will always contain the length of the message, not including
//the first 4 bytes. This is how you know when to stop reading.
tcpStream.Read(totalByteAray, 0, constIntSize);
//there are 4 bytes in a 32 bit number, so totalByteArrayContains 4 index that is a byte which is
//the 32 bit int that tells us how many bytes the whole message will be.
//now convert the totalByteArray to a 32bit int
totalBytes = BitConverter.ToInt32(totalByteAray, 0);
Console.WriteLine("reading " + totalBytes);
//fullMessage will contain the entire message but it has to be built message by message.
fullMessage = new byte[totalBytes];
//keep reading until we get all the data
while (currentBytes < totalBytes)
{
//when you send something over TCP it will some times get split up
//this is why you only read in chuncks, 4096 is a safe amount of bytes
//to split the data into.
if (totalBytes - currentBytes < constChunkSize)
{
chunkSize = totalBytes - currentBytes;
message = new byte[chunkSize];
}
tcpStream.Read(message, 0, chunkSize);
//since we know each chunk will always come in at 4096 bytes if it doesn't that means that it's the end
//this part cuts off the extra empty bytes
//copy the message to fullMessage starting at current bytes and ending with the bytes left
message.CopyTo(fullMessage, currentBytes);
currentBytes += chunkSize;
}
//message has successfully been received
if (totalBytes != 0)
{
if (OnRawDataReceived != null)
{
RawDataReceivedArgs args = new RawDataReceivedArgs();
args.Data = new byte[fullMessage.Length];
fullMessage.CopyTo(args.Data, 0);
OnRawDataReceived(this, args);
}
totalBytes = 0;
}
}
}
}
catch
{
connectionStatus = ConnectionStatus.NotConnected;
if (OnDisConnect != null)
OnDisConnect(this, null);
}
}
这是我发送数据的方式,我只获取消息的长度,然后创建一条新消息,前 4 个字节是消息的长度,其余是实际消息。
protected void sendData(byte[] data)
{
//we need to know how big the data that we are sending will be
int length = data.Length;
System.Console.WriteLine("writing " + length);
//convert the 32bit int to a 4 byte array
byte[] lengthArray = BitConverter.GetBytes(length);
//init the main byte array that will be sent over
byte[] buffer = new byte[length + constIntSize];
//the first 4 bytes will contain the length of the data
lengthArray.CopyTo(buffer, 0);
//the rest of the buffer will contain the data being sent
data.CopyTo(buffer, constIntSize);
//wite it to the client stream
tcpStream.Write(buffer, 0, length + constIntSize);
//now send it
tcpStream.Flush();
}
出于某种原因,我正在读取不应该在缓冲区中的数据。这是控制台输出。
服务器------------客户端
写1024 -> 读1024
阅读 1228800 <- 写作 1228800
写1024 -> 读1024
阅读 1228800 <- 写作 1228800
读书7224842
所以当我点击一个按钮时,它会发送一个请求说我想要一个来自网络摄像头的图像,这个请求是 1024 字节。客户端读取它并发送 1228800 字节的图像。我第一次这样做时,它总是有效。第二次单击它时,客户端发回了 1228800 字节,服务器读取了正确的字节数,然后在套接字缓冲区本应为空时发现了更多字节要读取。我在套接字缓冲区中没有 7224842 字节,这正是读取的前 4 个字节所说的。
关于缓冲区为什么在其中获取额外数据的任何想法?当我发送较小的消息时,一切似乎都运行良好,但这让我发疯。
最佳答案
tcpStream.Read(totalByteAray, 0, constIntSize);
...
tcpStream.Read(message, 0, chunkSize);
这就是整个问题。这是一项要求,您检查返回到此。不能保证(并且对于基于网络的 IO,不太可能)您会立即获得整个缓冲区 - 数据包会在任何时候进入,API 会为您提供它能做的。相反,您将得到“一些”(结果 > 0 且 <= 计数)或“无”(结果 <= 0)。
如果你想读取恰好那么多的数据,那么写一个实用方法:
static void ReadExact(Stream stream, byte[] buffer, int offset, int count)
{
int read;
while(count > 0 && (read = stream.Read(buffer, offset, count)) > 0) {
offset += read;
count -= read;
}
if(count != 0) throw new EndOfStreamException();
}
关于c# - NetworkStream 正在读取不应该存在的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9459880/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!