读取文件并通过套接字发送时出错

Error while reading the file and sending via sockets

本文关键字:出错 套接字 文件 读取      更新时间:2023-10-16

我正在读取一个文件并将其传输到c++服务器。以下是我的代码的主要部分:

客户:

long Begin;
long End;
char * block;
    //Open the file for reading
ifstream myfile;
myfile.open(path, ios::in | ios::binary);
    //Calculate the dize of file
Begin = myfile.tellg();
myfile.seekg(0,ios::end);
End = myfile.tellg();
unsigned long size = End - Begin;
int Div = (int)size / 1024;
int Mod = (int)size % 1024;
int len = strlen(name);
    //Send Length of filename
send(theSocket,(const char*)&len,sizeof(int),0);
recv(theSocket, ack,sizeof(ack),0);
    //Send Filename
send(theSocket,name,strlen(name),0);
recv(theSocket, ack,sizeof(ack),0);
    //Send size of file
send(theSocket, (const char*)&size, sizeof(unsigned long), 0);
recv(theSocket, ack,sizeof(ack),0);
    //send file in parts of 1024 bytes
for (int i=0; i<Div; i++)
{
    block = new char[1025];
    myfile.seekg(i*1024);
    myfile.get(block,1024);
            block[1024] = 0;
    send(theSocket,block,1025,0);
    recv(theSocket, ack,sizeof(ack),0);
}
    //send remaining part of file
if (Mod != 0)
{
    block = new char[Mod];
    myfile.seekg(Div*1024);
    myfile.get(block,Mod);
            block[Mod] = 0;
    send(theSocket,block,Mod+1,0);
    recv(theSocket, ack,sizeof(ack),0);
}
myfile.close();
closesocket(theSocket);
WSACleanup();

服务器:

while(true)
{
        theClient = accept(listeningSocket,NULL,NULL);
        int namelen;
        unsigned long filelen;
        char * block;
        char * Filename;
        char ack[10] = "Ack";
            //Receive Length of Filename
        recv(theClient,(char *)&namelen,sizeof(int),0);
        send(theClient,ack,sizeof(ack),0);
        Filename = new char [namelen];
            //Receive Filename
        recv(theClient,Filename,namelen,0);
        send(theClient,ack,sizeof(ack),0);
            //open file for writing         
        ofstream myfile;
        myfile.open(Filename, ios::out | ios::binary | ios::app);
            //Receive Length of File
        recv(theClient,(char *)&filelen,sizeof(unsigned long),0);
        send(theClient,ack,sizeof(ack),0);
        int Div = (int)filelen / 1024;
        int Mod = (int)filelen % 1024;
        block = new char[1024];
            //receive the file in parts and write to the stream
        for (int i=0; i<Div; i++)
        {
            recv(theClient,block,1025,0);
            myfile << block;
            send(theClient,ack,sizeof(ack),0);
        }
            //write the remaining part of file
        if (Mod != 0)
        {
            block = new char[Mod+1];
            recv(theClient,block,Mod,0);
            myfile << block;
            send(theClient,ack,sizeof(ack),0);
        }
        myfile.close();
    }

我已经成功创建套接字并建立连接。所以给那个代码没用。我有以下两个问题:

  1. 我错过了服务器上的每个1024th字节。这是因为我把zero放到了block的最后一个字节。但是我通过分配1025字节为zero保留了空间。

  2. 我无法处理CR/LF字符。当我以二进制模式传输文件时,我也必须照顾CR/LF。无论文件类型如何,我都需要传输文件。因此,如果观察到CR/LF,则终止字符串,并且数据不会作为server写入文件。

请帮忙解决。

我注意到服务器只分配了1024字节给block

您忽略了每个recv()调用的结果,并假设它填充了您提供的缓冲区。

TCP或伯克利套接字API规范中没有任何内容允许您这样做。recv()可以传递介于1字节和您指定的缓冲区长度之间的任何内容,也可以传递零,表示流结束或错误。您永远不能忽略这个结果