【问题标题】:Getting len of buffer for recv function获取 recv 函数的缓冲区长度
【发布时间】:2014-05-14 13:02:20
【问题描述】:

我编写了一个简单的 FTP 应用程序,它可以在客户端和服务器之间来回发送文件,并且运行良好。最近,我编写了一个用于客户端和服务器的套接字库,其中一些功能发生了变化,而且我在思考如何让它工作时遇到了麻烦。目前我正在我的服务器上集成库。

问题是我的部分规范是用库隐藏套接字句柄,所以我将“recv”和“send”包装在通过引用传递 char 指针的库函数中。在我实现这个之前,我将 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: %d\n", WSAGetLastError());
    }
    return bytes;
}

return -1;
}

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

【问题讨论】:

  • 您应该在receiveData 中使用switch
  • 我不确定我是否正确理解了您的问题。为什么将指针传递给数据指针而不是数据指针本身?在各种 C 风格的库中,通常的做法是将缓冲区和缓冲区的大小作为函数参数传递,并让函数返回实际写入的字节数或负错误代码。跨度>
  • 听起来你设计错了。应用程序应提供缓冲区及其长度。
  • 应用程序应该以什么方式提供缓冲区及其长度?
  • @CanadianCoder:看看recv 是如何做到的:你将缓冲区和缓冲区的大小传递给它,它会返回它已读取的字节数。您的函数应该这样做,并且实际上已经这样做了,以同样的方式。

标签: c++ sockets pointers char recv


【解决方案1】:

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

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

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

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

而是

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

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

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

【讨论】:

  • 我的印象是我需要通过我的库函数通过引用传递缓冲区。我发现一些页面建议将指针传递给指针是这样做的方法。本学期刚开始广泛使用指针,还没有完全理解它们!
  • 如果您希望函数能够修改指针本身,您只需要通过引用传递您的指针。但是你的函数只需要修改指针指向的数据,所以不需要引用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-04
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多