2012-04-22 116 views
1

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

发生什么事是:

  1. 客户端管理发送(send()方法调用)整个文件,意味着它的所有数据块。
  2. 服务器只管理第一个块的recv()调用,意味着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); 
+0

这里最可能的问题是网络丢弃/过滤的东西,或者是你的代码在某处的错误。 – Mat 2012-04-22 09:30:30

+0

如果网络没有任何东西,那么它也应该过滤第一个块。一个bug总是一种可能性,但是是一种什么样的?这是所有块的代码,因为它们是在一个循环中发送和接收的... – 2012-04-22 09:45:51

+0

C代码中存在尽可能多的错误,因为它的源文件中有字符(可能甚至超过这些)。没有看到你的代码的相关部分,没有人可以帮助你。 – Mat 2012-04-22 09:47:24

回答

0

您发送代码是错误的,它不会发送多块下正常情况下(即写入一次写入完整的块)。
这是因为在内循环之后,您不会重置bytesSent。在第一个sendBuf之后,机会将会是== FILE_READ_CHUNK_SIZE,并且在此之后,条件永远是错误的。

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

(有可能是你的代码的一些更多的错误。如果很短的写操作发生您要发送缓冲区的错件(你会重新发送缓冲区的头)的实例。)

+0

感谢分配垫!你发现我的错误:) – 2012-04-22 12:23:32