[英]System.OutOfMemoryException on server side for client files
我正在從客戶端獲取數據並將其保存到本地主機上的本地驅動器中。我已經檢查了它是否為221MB的文件,但是對1Gb的文件進行的測試給出了以下異常:
mscorlib.dll中發生了'System.OutOfMemoryException'類型的未處理異常
以下是在服務器端產生異常的代碼。
更新
服務器:
public void Thread()
{
TcpListener tcpListener = new TcpListener(ipaddr, port);
tcpListener.Start();
MessageBox.Show("Listening on port" + port);
TcpClient client=new TcpClient();
int bufferSize = 1024;
NetworkStream netStream;
int bytesRead = 0;
int allBytesRead = 0;
// Start listening
tcpListener.Start();
// Accept client
client = tcpListener.AcceptTcpClient();
netStream = client.GetStream();
// Read length of incoming data to reserver buffer for it
byte[] length = new byte[4];
bytesRead = netStream.Read(length, 0, 4);
int dataLength = BitConverter.ToInt32(length,0);
// Read the data
int bytesLeft = dataLength;
byte[] data = new byte[dataLength];
while (bytesLeft > 0)
{
int nextPacketSize = (bytesLeft > bufferSize) ? bufferSize : bytesLeft;
bytesRead = netStream.Read(data, allBytesRead, nextPacketSize);
allBytesRead += bytesRead;
bytesLeft -= bytesRead;
}
// Save to desktop
File.WriteAllBytes(@"D:\LALA\Miscellaneous\" + shortFileName, data);
// Clean up
netStream.Close();
client.Close();
}
我首先從客戶端獲取文件大小,然后再獲取數據。
1)。是否應該增加緩沖區大小或其他任何方法?
2)。 File.WriteAllBytes()
和File.ReadAllBytes()
似乎阻塞並凍結了PC。是否有任何異步方法可幫助提供服務器端接收到的文件的進度。
您無需在將整個內容寫入光盤之前將其讀取到內存中。 只需直接從網絡流復制到FileStream
:
byte[] length = new byte[4];
// TODO: Validate that bytesRead is 4 after this... it's unlikely but *possible*
// that you might not read the whole length in one go.
bytesRead = netStream.Read(length, 0, 4);
int bytesLeft = BitConverter.ToInt32(length,0);
using (var output = File.Create(@"D:\Javed\Miscellaneous\" + shortFileName))
{
netStream.CopyTo(output, bytesLeft);
}
請注意,您應該使用using
語句,而不是顯式調用netStream.Close()
:
using (Stream netStream = ...)
{
// Read from it
}
這樣,即使拋出異常,流也將關閉。
CLR的每個對象限制略微不足2GB。 但這是理論,實際上可以分配多少內存取決於框架允許分配的內存。 我不希望它允許您分配1 GB數據表。 您應該分配較小的表,並將數據分塊寫入磁盤文件。
之所以會發生“內存不足”異常,是因為您試圖在將整個文件轉儲到磁盤之前將其放置到內存中。 這不是最理想的,因為您不需要內存中的整個文件即可寫入文件:您可以以合理大小的增量逐塊讀取它,並隨即將其寫出。
從.NET 4.0開始,您可以使用Stream.CopyTo
方法在幾行代碼中完成此操作:
// Read and ignore the initial four bytes of length from the stream
byte[] ignore = new byte[4];
int bytesRead = 0;
do {
// This should complete in a single call, but the API requires you
// to do it in a loop.
bytesRead += netStream.Read(ignore, bytesRead, 4-bytesRead);
} while (bytesRead != 4);
// Copy the rest of the stream to a file
using (var fs = new FileStream(@"D:\Javed\Miscellaneous\" + shortFileName, FileMode.Create)) {
netStream.CopyTo(fs);
}
netStream.Close();
從.NET 4.5開始,您也可以使用CopyToAsync
,這將為您提供一種異步進行讀寫的方法。
請注意從流中刪除前四個字節的代碼。 這樣做是為了避免將流的長度與“有效載荷”字節一起寫入。 如果您可以控制網絡協議,則可以更改發送方以停止為其長度加上流前綴,並刪除在接收方讀取和忽略它的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.