1

クライアントからサーバーにファイルを送信するためのシンプルなクライアントサーバーアプリがあります。クライアントは、事前定義されたサイズ(たとえば、512)のチャンクでファイルを送信します。サーバーは、同じサイズのチャンクでもファイルを受信します。クライアント側のソケットは、サーバーがファイル全体を受信した後にackを送信するまで閉じられません。

何が起こるかです:

  1. クライアントは、ファイル全体、つまりすべてのチャンクを送信(send()呼び出し)することができます。
  2. サーバーは最初のチャンクのみを取得(recv()呼び出し)することができます。つまり、recv()呼び出しは、最初の呼び出しで512を返し、2番目の呼び出しでブロックします。

そのような行動の原因は何でしょうか?

関連する部分は次のとおりです。

送信/受信機能:

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

1 に答える 1

0

送信コードが間違っています。通常の状況では複数のチャンクを送信しません(つまり、書き込みは一度に完全なチャンクを書き込みます)。これは、内側のループの後で
リセットしないためです。bytesSentおそらく== FILE_READ_CHUNK_SIZE最初の後になり、その後sendBufはwhile条件が常にfalseになります。

したがって、送信するバッファは1つだけです。

(コードにはおそらくさらにいくつかのエラーがあります。たとえば、短い書き込みが発生した場合(バッファーの先頭を再送信します)、バッファーの間違った部分を送信します。)

于 2012-04-22T10:14:13.647 に答える