为什么不能通过tcp在C#中的客户端和C中的服务器之间正确传输(保存?)文件?
我已经在C中设置了TCP客户端,在C中设置了服务器。 当我想传输文件时,一些数据包丢失,文件保存不正确 我比较了我试图传输的PDF文件,有一半的数据包没有保存,所以我无法在另一台计算机上打开它 客户端代码:为什么不能通过tcp在C#中的客户端和C中的服务器之间正确传输(保存?)文件?,c#,c++,tcp,network-programming,C#,C++,Tcp,Network Programming,我已经在C中设置了TCP客户端,在C中设置了服务器。 当我想传输文件时,一些数据包丢失,文件保存不正确 我比较了我试图传输的PDF文件,有一半的数据包没有保存,所以我无法在另一台计算机上打开它 客户端代码: public void SendFile(string file, string destPath = "C:\\") { int bufferSize = 1024; byte[] filebuff = new byte[bufferSize];
public void SendFile(string file, string destPath = "C:\\")
{
int bufferSize = 1024;
byte[] filebuff = new byte[bufferSize];
string fileName = destPath + file;
//send to TcpServer request to send file
stream.Write(textToBytes("RECEIVEFILE"), 0, 11);
try
{
FileStream streamFile = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader binReader = new BinaryReader(streamFile);
//send file name to TcpServer
stream.Write(textToBytes(file), 0, file.Length);
//get file size
long filesize = streamFile.Length;
//send file size to TcpServer
//sendData(stream, BitConverter.GetBytes(filesize));
//if file doesn't exist
if (file == null)
{
Console.WriteLine("Error.");
}
//if file is empty
if (filesize == 0)
{
Console.WriteLine("File size: 0");
return;
}
int totalLength = Convert.ToInt32(filesize);
Console.WriteLine("Totallength: " + totalLength);
long numberOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(streamFile.Length) / bufferSize));
int currentPacketLength;
for (int i = 0; i < numberOfPackets; i++)
{
if (filesize > bufferSize)
{
currentPacketLength = bufferSize;
totalLength = totalLength - currentPacketLength;
}
else
currentPacketLength = totalLength;
filebuff = new byte[currentPacketLength];
//streamFile.Read(filebuff, 0, currentPacketLength);
binReader.Read(filebuff, 0, currentPacketLength);
stream.Write(filebuff, 0, filebuff.Length);
}
streamFile.Close();
}
catch
{
Console.WriteLine("There's no file...");
}
}
public void DownloadFile(string fileName)
{
byte[] recBuffer = new byte[1024];
byte[] fileNameBytes;
long received = 0;
long receivedAll = 0;
byte[] fileData = new byte[1024];
stream.Write(textToBytes("SENDFILE"), 0, 8);
fileNameBytes = Encoding.UTF8.GetBytes(fileName);
stream.Write(fileNameBytes, 0, fileNameBytes.Length);
byte[] fileSizeBytes = new byte[4];
stream.Read(fileSizeBytes, 0, fileSizeBytes.Length);
int bytes = BitConverter.ToInt32(fileSizeBytes, 0);
Console.WriteLine("I'm downloading file...");
while (receivedAll < bytes)
{
received = stream.Read(fileData, 0, fileData.Length);
if (received < 0)
{
Console.WriteLine("Error");
break;
}
BinaryWriter bWrite = new BinaryWriter(File.Open("C:\\" + fileName, FileMode.Append));
bWrite.Write(fileData);
bWrite.Close();
receivedAll += received;
}
if(receivedAll == bytes)
{
Console.WriteLine("File downloaded successfuly.");
}
}
public void SendFile(string file,string destPath=“C:\\”)
{
int bufferSize=1024;
byte[]filebuff=新字节[bufferSize];
字符串文件名=destPath+文件;
//发送到TcpServer发送文件的请求
stream.Write(textToBytes(“RECEIVEFILE”),0,11;
尝试
{
FileStream streamFile=新FileStream(文件名,FileMode.Open,FileAccess.Read);
BinaryReader=新的BinaryReader(流文件);
//将文件名发送到TcpServer
stream.Write(textToBytes(file),0,file.Length);
//获取文件大小
long filesize=streamFile.Length;
//将文件大小发送到TcpServer
//sendData(stream,BitConverter.GetBytes(filesize));
//如果文件不存在
if(file==null)
{
控制台。WriteLine(“错误”);
}
//如果文件为空
如果(文件大小==0)
{
Console.WriteLine(“文件大小:0”);
返回;
}
int totalength=Convert.ToInt32(文件大小);
控制台写入线(“总长度:+Totallength”);
long numberOfPackets=Convert.ToInt32(Math.天花(Convert.ToDouble(streamFile.Length)/bufferSize));
int currentPacketLength;
对于(int i=0;i缓冲大小)
{
currentPacketLength=缓冲区大小;
totalLength=totalLength-当前包装长度;
}
其他的
currentPacketLength=总长度;
filebuff=新字节[currentPacketLength];
//读取(filebuff,0,currentPacketLength);
读取(filebuff,0,currentPacketLength);
stream.Write(filebuff,0,filebuff.Length);
}
streamFile.Close();
}
抓住
{
WriteLine(“没有文件…”);
}
}
公共无效下载文件(字符串文件名)
{
字节[]recBuffer=新字节[1024];
byte[]fileNameBytes;
长期接收=0;
长接收DALL=0;
字节[]文件数据=新字节[1024];
stream.Write(textToBytes(“SENDFILE”),0,8;
fileNameBytes=Encoding.UTF8.GetBytes(文件名);
stream.Write(fileNameBytes,0,fileNameBytes.Length);
字节[]fileSizeBytes=新字节[4];
Read(fileSizeBytes,0,fileSizeBytes.Length);
int bytes=BitConverter.ToInt32(fileSizeBytes,0);
WriteLine(“我正在下载文件…”);
while(receivedAll<字节)
{
接收=stream.Read(fileData,0,fileData.Length);
如果(接收<0)
{
控制台写入线(“错误”);
打破
}
BinaryWriter bWrite=新的BinaryWriter(File.Open(“C:\\”+fileName,FileMode.Append));
b写入(文件数据);
bWrite.Close();
receivedAll+=已接收;
}
if(receivedAll==字节)
{
WriteLine(“文件下载成功”);
}
}
服务器代码:
void ReceiveFile(int client_socket)
{
const int buffsize = 1024;
char buff[buffsize];
long filesize, received = 0, receivedall;
char filenamechar[512];
std::string filename, fullFilename;
memset(filenamechar, 0, 512);
/*
if(recv(client_socket, filenamechar, 512, 0) != 512)
{
printf("Error - filename.\n");
return;
}
fullFilename = "/Users/xxx/" + std::string(filenamechar);
*
if(recv(client_socket, &filesize, sizeof(long), 0) != sizeof(long))
{
printf("Child process: error.\n");
return;
}*/
filesize = 331776;
std::fstream fileFromClient;
fullFilename = "/Users/xxx/sockets.pdf";
fileFromClient.open(fullFilename, std::ios::binary | std::ios::out);
receivedall = 0;
while (receivedall < filesize)
{
memset(buff, 0, 1024);
received = recv(client_socket, buff, 1024, 0);
if(received <= 0)
{
std::cout << "error" << std::endl;
break;
}
receivedall += received;
fileFromClient << buff;
fputs(buff, stdout);
}
fileFromClient.close();
std::cout << "\nreceivedall: " << receivedall << std::endl;
std::cout << "filesize: " << filesize << std::endl;
if(receivedall != filesize)
printf("Error\n");
else
printf("File saved successfuly\n");
}
void SendFile(int client_socket)
{
char path[512];
char fileName[512];
char fullFileName[512];
long fileLen, sent, sentAll, read;
struct stat fileinfo;
FILE* file;
unsigned char bufor[1024];
memset(path, 0, 512);
strcpy(path, "/Users/xxxx/");
if (recv(client_socket, fileName, 512, 0) <= 0)
{
printf("Child process: error\n");
return;
}
strcpy(fullFileName, strcat(path, fileName));
printf("Child process: client wants file: %s\n", fullFileName);
if (stat(fullFileName, &fileinfo) < 0)
{
printf("Child process: can't get file info\n");
return;
}
if (fileinfo.st_size == 0)
{
printf("Child process: file size: 0\n");
return;
}
fileLen = fileinfo.st_size;
if (send(client_socket, &fileLen, sizeof(long), 0) != sizeof(long))
{
printf("Child process: error\n");
return;
}
sentAll = 0;
file = fopen(fullFileName, "rb");
if (file == NULL)
{
printf("Error\n");
return;
}
while (sentAll < fileLen)
{
read = fread(bufor, 1, 1024, file);
sent = send(client_socket, bufor, read, 0);
if (read != sent)
break;
sentAll += sent;
printf("Child process: sent %ld bytes\n", sentAll);
}
if (sentAll == fileLen)
printf("Child process: file sent successfuly\n");
else
printf("Child process: error\n");
fclose(file);
return;
}
void-ReceiveFile(int-client\u-socket)
{
常量int buffsize=1024;
字符buff[buffsize];
长文件大小,received=0,receivedall;
char filenamechar[512];
std::字符串文件名,fullFilename;
memset(filenamechar,0512);
/*
if(recv(client_socket,filenamechar,512,0)!=512)
{
printf(“错误-文件名。\n”);
返回;
}
fullFilename=“/Users/xxx/”+std::string(filenamechar);
*
if(recv(client_socket,&filesize,sizeof(long),0)!=sizeof(long))
{
printf(“子进程:错误。\n”);
返回;
}*/
filesize=331776;
std::fstream fileFromClient;
fullFilename=“/Users/xxx/sockets.pdf”;
fileFromClient.open(fullFilename,std::ios::binary | std::ios::out);
receivedall=0;
while(receivedall 如果(接收到此线路有一个问题:
fileFromClient << buff;
无关:使用char filenamechar[512]={0}保存对memset
的调用;
这将使用您在{}中输入的任何数字初始化数组中的第一个空格
s并用零填充数组的其余部分。接收端不知道数据的结束位置。因此,必须先发送带有大小的数据。然后在接收端删除大小并读取,直到获得所有字节。无关:通过更改received=recv,为自己节省另一个memset
和一些其他麻烦(client_socket,buff,1024,0);
toreceived=recv(client_socket,buff,sizeof(buff)-1,0);
sizeof(buff)
删除神奇数字1024,将读取的最大大小与缓冲区大小锁定在一起,这样您就不能更改buff
的大小,然后忘记更改读取量。-1确保您有空终止符的空间,否则fileFromClient您不应使用格式写入数据在SendFile
,if(recv(客户端套接字,文件名,512,0)
fileFromClient.write(buff, received);