c - recv() 阻止第二次调用

标签 c linux sockets recv

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

发生的事情是:

  1. 客户端设法发送(send() 调用)整个文件,即所有文件 block 。
  2. 服务器设法仅获取(recv() 调用)第一个 block ,这意味着 recv() 调用在第一次调用时返回 512,在第二次调用时它会阻塞。

这种行为的原因可能是什么?

这里是相关的部分。

发送\接收函数:

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

最佳答案

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

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

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

关于c - recv() 阻止第二次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10266785/

相关文章:

c# - 网络套接字-仅第一条消息总是会完成

sockets - 从应用程序重置 TCP 套接字连接

c - malloc 和 strcpy 交互

c++ - typedef'ing 结构对自身的影响是什么?

c - 如何使用 malloc 函数将结构复制到指针中 [C 编程]

c - 非阻塞 tcp 套接字如何通知应用程序发送失败的数据包。

linux - 命令在 CLI 中有效,但 1 在脚本中无效

c - UDP - 多服务器单客户端

linux - 如果我没有得到预期的整数值,我该如何终止我的脚本? - BASH shell 脚本

java - 从 Camel 路由在 ActiveMQ 上强制套接字超时?