简体   繁体   中英

recv() blocks from second call

I have a simple client-server app for sending files from client to server. The client sends the file in chunks of predefined size (say 512). The server receives the file also in chunks with the same size. The socket on the client side isn't closed until the server sends an ack after receiving the entire file.

What happens is that:

  1. the client manages to send (send() call) the entire file, means all its chunks.
  2. the server manages to get (recv() call) only the first chunk, means recv() call returned 512 on the first call and on the second call it blocks.

What might be the cause for such behavior?

Here are the relevant parts.

Send\\Receive functions:

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;
}

Server:

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);

Client:

/* 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);

Your sending code is wrong, it won't send more than one chunk under normal circumstances (ie the write writes a full chunk in one go).
This is because you don't reset bytesSent after the inner loop. Chances are it is going to be == FILE_READ_CHUNK_SIZE after the first sendBuf , and the while condition will always be false after that.

So you're only sending one buffer.

(There are probably a few more errors in your code. You'll be sending the wrong parts of the buffer if a short write happens (you'll resend the head of your buffer) for instance.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM