问题是你忽略了返回值Receive()
。无法保证您的缓冲区将被完全填满。
返回值告诉您套接字实际从网络读取了多少数据。调整您的接收代码,以便将其考虑在内。发送也是如此。如果内部套接字缓冲区已满,它将报告发送的字节数少于您请求发送的字节数。
除此之外,我建议您开始为变量指定有意义的名称。您的代码的可读性不太好。
这是一个更好的接收例程:
var fileBuffer = new byte[size];
var receiveBuffer = new byte[2048];
var bytesLeftToReceive = size;
var fileOffset = 0;
while (bytesLeftToReceive > 0)
{
//receive
var bytesRead = client.Receive(receiveBuffer);
if (bytesRead == 0)
throw new InvalidOperationException("Remote endpoint disconnected");
//if the socket is used for other things after the file transfer
//we need to make sure that we do not copy that data
//to the file
int bytesToCopy = Math.Min(bytesRead, bytesLeftToReceive);
// copy data from our socket buffer to the file buffer.
Buffer.BlockCopy(receiveBuffer, 0, bytesLeftToReceive, fileBuffer, fileOffset);
//move forward in the file buffer
fileOffset += bytesToCopy;
//update our tracker.
bytesLeftToReceive -= bytesToCopy;
}
但是,既然要传输大文件,那么直接将其写入文件流不是更好吗?
var stream = File.Create(@"C:\path\to\file.dat");
var receiveBuffer = new byte[2048];
var bytesLeftToReceive = size;
while (bytesLeftToReceive > 0)
{
//receive
var bytesRead = client.Receive(receiveBuffer);
if (bytesRead == 0)
throw new InvalidOperationException("Remote endpoint disconnected");
//if the socket is used for other things after the file transfer
//we need to make sure that we do not copy that data
//to the file
int bytesToCopy = Math.Min(bytesRead, bytesLeftToReceive);
// write to file
stream.Write(receiveBuffer, 0, bytesToCopy);
//update our tracker.
bytesLeftToReceive -= bytesToCopy;
}
在发送端我会做这样的事情:
// read directly from the file to reduce memory usage.
var fileName = @"....";
using (var file = File.OpenRead(fileName))
{
var sendBuffer = new byte[2048];
var fileSize = BitConverter.GetBytes((int)file.Length);
server.Send(fileSize, fileSize.Length, SocketFlags.None);
var bytesLeftToTransmit = fileSize;
while (bytesLeftToTransmit > 0)
{
var dataToSend = file.Read(sendBuffer, 0, sendBuffer.Length);
bytesLeftToTransmit -= dataToSend;
//loop until the socket have sent everything in the buffer.
var offset=0;
while (dataToSend > 0)
{
var bytesSent = socket.Send(sendBuffer, offset, dataToSend);
dataToSend -= bytesSent;
offset += bytesSent;
}
}
}
最后你有一个套接字发送文件 https://msdn.microsoft.com/en-us/library/sx0a40c2(v=vs.110).aspx已针对发送文件进行了优化。您可以随时为打开的套接字调用它。