为什么不能通过tcp在C#中的客户端和C中的服务器之间正确传输(保存?)文件?

为什么不能通过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];

我已经在C中设置了TCP客户端,在C中设置了服务器。 当我想传输文件时,一些数据包丢失,文件保存不正确

我比较了我试图传输的PDF文件,有一半的数据包没有保存,所以我无法在另一台计算机上打开它

客户端代码:

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);
to
received=recv(client_socket,buff,sizeof(buff)-1,0);
sizeof(buff)
删除神奇数字1024,将读取的最大大小与缓冲区大小锁定在一起,这样您就不能更改
buff
的大小,然后忘记更改读取量。-1确保您有空终止符的空间,否则
fileFromClient您不应使用格式写入数据
SendFile
if(recv(客户端套接字,文件名,512,0)
fileFromClient.write(buff, received);