获取用于 recv 功能的缓冲区的镜头

Getting len of buffer for recv function

本文关键字:缓冲区 功能 用于 recv 获取      更新时间:2023-10-16

我编写了一个简单的FTP应用程序,可以在客户端和服务器之间来回发送文件,并且工作正常。最近,我编写了一个用于客户端和服务器的套接字库,某些功能已更改,并且我无法理解如何使其工作。目前,我正在服务器上集成库。

问题是我的规范的一部分是隐藏库的套接字句柄,所以我将"recv"和"send"包装在通过引用传递字符指针的库函数中。在我实现这一点之前,我将 char[] 直接传递到 recv 函数中,该函数足以满足我的目的。现在我正在使用 char*,似乎我需要知道传入消息的确切长度,因为我的 char* 与发送数据和垃圾字符一起出现。

这是我的服务器代码的一部分:

while (true)
{       
    command = (char*)malloc(sizeof(char)*32);
    int bytesRecv = socketObject.receiveData('c', &command, 32);        
    if(_stricmp(command,"mput") == 0)
    {
        while( true ) {
             SizeCheck = 0;
             FileSize = 0;
             fileName = (char*)malloc(sizeof(char)*1024);                
             bytesRecv = socketObject.receiveData('c', &fileName, 1024);
             if(_stricmp(fileName,"goodbye") == 0)
             {                      
                break;
             }
            while( true )
            {
                char GotFileSize[1024];
                GotFileSize = (char*)malloc(sizeof(char)*1024); 
                socketObject.receiveData('c', &sentSize, 1024);

                FileSize = atoi(GotFileSize);
                if (FileSize > 0)
                {   
                    break;
                }
            }
            mfcc = (char*)malloc(sizeof(char)*FileSize);
            FILE *fp;
            if( (fp = fopen(fileArray, "wb")) == NULL)
            {
                std::cout << "fopen has caused an error" << endl;
            }
            while(SizeCheck < FileSize){
                int Received = socketObject.receiveData('f', &mfcc, FileSize);              
                if(Received != SOCKET_ERROR)
                {   
                    std::cout << "Before fwrite" << std::endl;
                    int written = fwrite(mfcc, 1, FileSize, fp);
                    SizeCheck += Received;
                    fflush(fp);
                }   
            }//while transfer
        }//while true
    }//end mput if

这是我的接收函数:

int Socket::receiveData( char socketType, char** data, int size)
{
if(socketType != 'f' && socketType != 'c')
{
    return -1;
}
if(socketType == 'f')
{
    int bytes = recv( fAccepted, *data, size, 0);
    return bytes;
}
else if(socketType == 'c')
{   
    int bytes = recv( cAccepted, *data, size, 0);
    if (bytes == SOCKET_ERROR) {
        printf("send failed: %dn", WSAGetLastError());
    }
    return bytes;
}
return -1;
}

我已经对recv进行了一些阅读,告诉我应该以某种方式发送文件名的大小和文件名,或者在循环中编译一个完整的字符串。我不确定这些方法是否适合我正在尝试做的事情,或者是否有更简单的方法。

receiveData函数非常好:它将收到的字节写入缓冲区,并返回接收的字节数。

缓冲区中的所有其他字节可以且应该忽略。在当前代码中,每次接收数据时,都会将整个缓冲区写入文件,即使receiveData准确地告诉您应写入多少数据。

也就是说,你不应该这样做

int written = fwrite(mfcc, 1, FileSize, fp);

而是相反

int written = fwrite(mfcc, 1, Received, fp);

您应该考虑使用更合理的缓冲区大小,例如 1500 字节(网络数据包的常用 MTU)或 1MB(应该可以毫无问题地放入 RAM 的大小),而不是完整的文件大小。

顺便说一下,没有必要将data作为双指针传递,或者,正如你所说的,作为对指针的引用。只需将其作为普通指针传递即可。但这与您的"垃圾数据"问题无关。