recv()阻止第二次调用

时间:2012-04-22 09:27:58

标签: c linux sockets recv

我有一个简单的客户端 - 服务器应用程序,用于从客户端向服务器发送文件。 客户端以预定义大小的块(例如512)发送文件。 服务器也以相同大小的块接收文件。 在服务器收到整个文件后发送确认时,客户端的套接字才会关闭。

会发生什么:

  1. 客户端设法发送(send()调用)整个文件,意味着它的所有块。
  2. 服务器设法获取(recv()调用)只有第一个块,意味着recv()调用在第一次调用时返回512,在第二次调用时它阻止。
  3. 这种行为可能是什么原因?

    以下是相关部分。

    发送\接收功能:

    int sendBuf(int sockFd, char* buf, int size){
        int bytesSent = 0;
        while (bytesSent < size){
            bytesSent += send(sockFd, buf, size, 0);
        }
        return bytesSent;
    }
    
    
    int sendInt(int sockFd, int num){
        uint32_t nbo_num = htonl(num);
        return sendBuf(sockFd, (char*)&nbo_num, sizeof(nbo_num));
    }
    
    
    int getBuf(int sockFd, char* buf, int size){
        int bytesRecv = 0;
        while (bytesRecv < size){
            bytesRecv += recv(sockFd, buf, size, 0);
        }
        return bytesRecv;
    }
    
    
    int getInt(int sockFd, int *num){
        int temp, bytesRecv;
        bytesRecv = getBuf(sockFd, (char*)&temp, sizeof(int));
        *num = ntohl(temp);
        return bytesRecv;
    }
    

    服务器:

    printf("%s     New file was created.\n",tStr);
    
    /* get file data */
    char buf[FILE_READ_CHUNK_SIZE] = {0}; // FILE_READ_CHUNK_SIZE is the maximal read amount
    int bytesWritten = 0, bytesLeft = fileSize, _size=0, chunkNo=0;
    bytesRecv = 0;
    
    while (bytesLeft > 0){
        _size = (bytesLeft > FILE_READ_CHUNK_SIZE) ? FILE_READ_CHUNK_SIZE : bytesLeft;
        bytesRecv = getBuf(newsockfd, buf, _size);
        int _bytesLeft = bytesRecv;
        bytesWritten = 0;
        while (_bytesLeft > 0){
            bytesWritten = fileInfoWrite(fileInfo, buf, _bytesLeft);
            _bytesLeft -= bytesWritten;
        }
        chunkNo++;
        printf("%s     chunk #%d: received %d bytes\n",tStr , chunkNo, bytesRecv);
        bytesLeft -= bytesRecv;
    }
    printf("%s   Finished getting file #%d.\n",tStr ,i+1);
    
    /* send ack to the client */
    bytesSent = sendInt(newsockfd, 1);
    printf("%s   Sent the client an  ack for file #%d.\n",tStr ,i+1);
    

    客户端:

    /* send the entire data of the file */
    printf("  Sending file data\t\t... ");
    char buf[FILE_READ_CHUNK_SIZE] = {0}; // FILE_READ_CHUNK_SIZE is the maximal read amount
    int numOfChunks=0, bytesRead = 0, bytesLeft = filesArr[i]->fileSize ;
    bool eof = false;
    bytesSent = 1;
    
    while (bytesLeft > 0){
        bytesRead = fileInfoRead(filesArr[i], buf, &eof);
        int _bytesLeft = bytesRead;
        while (bytesSent < _bytesLeft){
            bytesSent = sendBuf(sockFd, buf, _bytesLeft);
            _bytesLeft -= bytesSent;
        }
        //printf("    chunk #%d: sent %d bytes\n", numOfChunks+1, bytesRead);
        bytesLeft -= bytesRead;
        numOfChunks++;
    }
    printf("Success.\n");
    
    /* get ack from server */
    int ack=0;
    bytesRecv = getInt(sockFd, &ack);
    if (bytesRecv!=4 || ack!=1){
        printf("Server ack is invalid.\n");
    }
    printf("Finished sending file #%d.\n",i+1);
    

1 个答案:

答案 0 :(得分:0)

您的发送代码错误,在正常情况下不会发送多个块(即写入一次写入一个完整的块)。
这是因为在内循环后你没有重置bytesSent。在第一个== FILE_READ_CHUNK_SIZE之后,它可能会sendBuf,之后的条件将始终为false。

所以你只发送一个缓冲区。

(你的代码中可能还有一些错误。例如,如果发生短写,你将发送缓冲区的错误部分(你将重新发送缓冲区的头部)。)