我正在使用c#传输文件。我使用过this代码。问题是像.txt文件这样的小文件是正确传输的,但不是大文件,如图像,文档,pdf,ppt。有时代码工作正常,但大多数情况下它传输的数据量较少。
服务器代码:
Socket clientSock = sock.Accept();
byte[] clientData = new byte[1024 * 50000];
int receivedBytesLen = clientSock.Receive(clientData);
int fileNameLen = BitConverter.ToInt32(clientData, 0);
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath + "/" + fileName, FileMode.Append));
bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen);
bWrite.Close();
clientSock.Close();
客户代码:
byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName);
byte[] fileData = File.ReadAllBytes(filePath + fileName);
byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileNameByte.Length);
clientSock.Connect(ipEnd);
clientSock.Send(clientData);
clientSock.Close();
完整代码在上面的链接中给出。我也见过这个post,但这没有帮助。
答案 0 :(得分:4)
有时代码工作正常,但大多数时候它传输的数据量较少。
这是Socket.Receive()
的本质,它并不总是返回发送给它的所有数据。
您必须首先Receive(clientData, 4, 0)
接收指示size
的字节,然后在循环中调用Receive(clientData)
,直到您收到size
个字节为止。但请注意,Receive(buffer[], length, offset)
重载与任何其他重载一样容易返回 less 而不是预期的字节数。所以你还必须在循环中调用它:
这样的事情:
// First receive the size
int sizeSize = 4; // Size of Int32 in bytes
int sizeOffset = 0;
var sizeBytes = new byte[sizeSize];
while (sizeOffset < sizeSize)
{
sizeOffset += clientSocket.Receive(sizeBytes, sizeSize - sizeOffset, sizeOffset);
}
var size = BitConverter.ToInt32(sizeBytes, 0);
// Then receive the data
byte[] fileData = new byte[size];
byte[] clientData = new byte[8192];
int totalBytes = 0;
while (totalBytes < size)
{
// This may return anything between 0 and 8192, even if not all sent data has been received yet. It may be in a buffer somewhere, waiting to be picked up. Check for 0, since that's when the client disconnects.
int bytesReceived = clientSocket.Receive(clientData);
// You now have received a chunk of data of bytesReceived length. Append it into the fileData array.
Buffer.BlockCopy(clientData, 0, fileData, totalBytes, bytesReceived);
totalBytes += bytesReceived;
}
答案 1 :(得分:0)
正如 CodeCaster的回答Socket.Receive(), it doesn't always return all data that gets sent to it.
这是100%正确并经过测试但发送文件大小的下一步无效,我找到了一个简单而正确的解决方案。
Socket.Receive()
方法获取将复制接收数据的字节数组,并返回接收的字节数。所以我们可以轻松地循环它直到收到的字节为0。
byte[] tempData = new byte[1024 * 5000];
BinaryWriter bWrite = null;
int bytes_received;
int fileNamelength = 0;
bool isFirstPacket = true;
do
{
bytes_received = clientSock.Receive(tempData);
if(isFirstPacket)
{
isFirstPacket = false;
int fileNameLen = BitConverter.ToInt32(tempData, 0);
string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen);
bWrite = new BinaryWriter(File.Open(receivedPath + fileName, FileMode.Append))
bWrite.Write(tempData, 4 + fileNameLength, bytes_received - 4 - fileNamelength);
}
else
bWrite.Write(tempData, 0, bytes_received);
}
while (bytes_received != 0);