通过网络读取数据时,指定一个缓冲区以将数据接收到:
byte[] b = new byte[4096];
socket.Receive(b);
现在我的第一个想法当然是通过将它声明为类的成员变量来重用接收缓冲区。我的下一个问题是我没有收到我期望的所有数据,所以我需要缓冲我的数据。通过跟踪接收的字节数并指定偏移量,可以很容易地实现这一点:
socket.Receive(m_ReceiveBuffer, count, m_ReceiveBuffer.Length - count);
现在,问题在于,如果仍然不够,我猜我需要增加缓冲区,这意味着复制内存,并继续接收到此缓冲区。假设出现问题,此缓冲区将继续增长,如果收到足够大的消息,则会使系统内存不足。
任何想法如何正确处理这个?是否有更好的方式来接收数据,而不仅仅是填充,复制,增长,填充,复制,增长我正在谈论的内容?
答案 0 :(得分:2)
读取块:
const int ChunkSize = 4096;
int bytesRead;
byte[] buffer = new byte[ChunkSize];
while ((bytesRead = socket.Receive(buffer, 0, ChunkSize, SocketFlags.None)) > 0)
{
byte[] actualBytesRead = new byte[bytesRead];
Buffer.BlockCopy(buffer, 0, actualBytesRead, 0, bytesRead);
// Do something with actualBytesRead,
// maybe add it to a list or write it to a stream somewhere
}
答案 1 :(得分:1)
在开始使用SYstem.Net.Sockets.Socket之前,您确定不能使用System.Net.Sockets.TcpClient(或UdpClient)来为您完成所有混乱的缓冲区工作并将其转换为易于管理的流?
如果没有,请记住,您收到的数据量不必等于您要求的数据,因此您应始终查看接收函数的返回值。并且,不会耗尽内存的唯一方法是实际处理您收到的内容。
答案 2 :(得分:0)
首先,将代码分离为接收数据和处理数据。接收缓冲区应该只保存数据,直到代码有机会将其复制到处理区域。您可以在处理区域确定是否已收到足够的数据来执行有用的操作。在发生这种情况之前,请勿将数据保留在网络接收缓冲区中。对于网络接收缓冲区,我认为使用循环缓冲区可以帮助您重新使用缓冲区。希望您对消息大小有所了解。这将有助于确定缓冲区的大小。如果在循环缓冲区的读写指针满足时断言(或类似),则增加缓冲区的大小。一旦缓冲区的大小足够大,您应该能够以足够快的速率从缓冲区中读取足够的数据到循环缓冲区不会溢出。