[英]Not sending file correctly. Sockets. C
I am writing a program that a client can ask for files to a server. 我正在编写一个客户端可以向服务器请求文件的程序。 Then the server will send them in chunks of 512 bytes. 然后,服务器将以512字节的块发送它们。 The problem is that when the client read the file: 问题是当客户端读取文件时:
*Sometimes the first 512 bytes are different from the original file. *有时前512个字节与原始文件不同。 The total read file also has a different size (and obviously it also ends different from the original file) and therefore the client loop that writes to the new file does never end. 总读取文件的大小也不同(显然,它的结束也不同于原始文件),因此写入新文件的客户端循环永远不会结束。
*Sometimes it works perfectly and i don't know why. *有时效果很好,我不知道为什么。
Server: 服务器:
/* Check if file exists */
if(access(retrFileName, F_OK) == 0){
/* Open file */
fd = open(retrFileName, O_RDONLY);
lseek(fd, 0, SEEK_SET);
if (fd == -1){
fprintf(stderr, "Error opening file --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Get file stats */
if (fstat(fd, &fileStat) < 0){
fprintf(stderr, "Error fstat --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
sprintf(fileSize, "%li", fileStat.st_size);
/* Sending file data */
offset = 0;
remainData = fileStat.st_size;
while (((sentBytes = sendfile(clientSock, fd, &offset, 512)) == 512) && (remainData > 0)) {
remainData -= sentBytes;
fprintf(stdout, "Server envio %d bytes del file, offset ahora vale: %li y quedan = %d bytes\n", sentBytes, offset, remainData);
}
remainData -= sentBytes;
fprintf(stdout, "Server envio %d bytes del file, offset ahora vale: %li y quedan = %d bytes\n", sentBytes, offset, remainData);//do while
close(fd);////////////////////////
send(clientSock, NICETRANSFER, sizeof(NICETRANSFER), 0); //LO METE AL ARCHIVO
printf("send\n");
//close(clientSock);///////////
}
else{
send(clientSock, FILEERROR, sizeof(FILEERROR), 0);
printf("send\n");
}
}
Client: 客户:
/* Open file */
receivedFile = fopen("r.txt", "wb");
if (receivedFile == NULL){
fprintf(stderr, "Failed to open file --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
/* Write to the file */
int contador = 0;
int remainData = fileSize;
do{
if(remainData < 512)
bytesLeidos = recv(clientSock, readingBuffer, remainData, 0);
else
bytesLeidos = recv(clientSock, readingBuffer, 512, 0);
fwrite(readingBuffer, bytesLeidos, 1, receivedFile);
remainData -= 512;
contador += 512;
printf("bytesleidos: %li, contador: %d:\n%s\n\n", bytesLeidos, contador, readingBuffer);
}while(contador < fileSize);
fclose(receivedFile);
Golden rule of socket programming: Always check the return value from recv
. 套接字编程的黄金法则:始终检查recv
的返回值。 It's not always what you think it will be. 这并不总是您所想的。
Even though you "send" 512 bytes at a time, you are in no way guaranteed that TCP will deliver the same number of bytes at a time to the receiver. 即使您一次“发送” 512个字节,也无法保证TCP一次将相同数量的字节发送给接收方。 TCP segmentation, IP fragmentation, and general Internet weirdness will cause the recv side to get an arbitrary number of bytes at a time. TCP分段,IP分段和一般的Internet异常会导致recv一次获取任意数量的字节。
Hence, your hardcoded assumption that recv
will always return 512 is incorrect: 因此,您对recv
将始终返回512的硬编码假设是不正确的:
remainData -= 512;
contador += 512;
Instead, you should be saying: 相反,您应该说:
remainData -= bytesLeidos;
contador += bytesLeidos;
An you need to check for errors and socket closing too. 您还需要检查错误和套接字关闭。
This is an improved main loop for your client code: 这是客户端代码的改进的主循环:
while (remainData > 0)
{
size_t recvSize = (remainData >= 512) ? 512 : remainData;
bytesLeidos = recv(clientSock, readingBuffer, recvSize, 0);
if (bytesLeidos > 0)
{
fwrite(readingBuffer, bytesLeidos, 1, receivedFile);
remainData -= bytesLeidos;
contador += bytesLeidos;
/* null terminate readingBuffer so garbage isn't printed.*/
/* Make sure readingBuffer is allocated to be at least */
/* N+1 bytes (513) to account for this character being appended. */
readingBuffer[bytesLeidos] = '\0';
printf("bytesleidos: %li, contador: %d:\n%s\n\n", bytesLeidos, contador, readingBuffer);
}
else if (bytesLeidos == 0)
{
/* remote side closed connection */
printf("Remote side exited connection\n");
break;
}
else if (bytesLeidos < 0)
{
/* connection error */
printf("Connection error\n");
break;
}
}
I solved my problem!! 我解决了我的问题! I needed to sync both client and server. 我需要同步客户端和服务器。 To do so, the server send the size of the file and waits for an answer for the client with recv
. 为此,服务器发送文件的大小,并使用recv
等待客户端的答案。 When the client recieve the file size, it send
a "" message. 当客户端收到文件大小时,它将send
“”消息。
I don't know if this is the correct solution, but this way you can sync server and client. 我不知道这是否是正确的解决方案,但是您可以通过这种方式同步服务器和客户端。
After sync, the server send the respective file normally with sendfile
同步后,服务器使用sendfile
正常发送各自的文件
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.