c发送和接收文件
这是服务器(发送文件)部分: 客户端从服务器接收fsize,代码为:c发送和接收文件,c,sockets,sendfile,C,Sockets,Sendfile,这是服务器(发送文件)部分: 客户端从服务器接收fsize,代码为: fd = open(filename, O_RDONLY); if(fd < 0){ error!! } if(fstat(fd, &fileStat) < 0){ perror("Errore fstat"); onexit(newsockd, sockd, fd, 3); } fsize = fileStat.st_s
fd = open(filename, O_RDONLY);
if(fd < 0){
error!!
}
if(fstat(fd, &fileStat) < 0){
perror("Errore fstat");
onexit(newsockd, sockd, fd, 3);
}
fsize = fileStat.st_size;
if(send(newsockd, &fsize, sizeof(fsize), 0) < 0){
perror("Errore durante l'invio della grandezza del file\n");
onexit(newsockd, sockd, fd, 3);
}
if(read(sockd, &fsize, sizeof(fsize)) < 0){
perror("Errore durante ricezione grandezza file\n");
onexit(sockd, 0 ,0 ,1);
}
fd = open(sInfo.filename, O_CREAT | O_WRONLY, 0644);
if (fd < 0) {
perror("open");
onexit(sockd, 0 ,0 ,1);
}
fsize_tmp = fsize;
if(读取(sockd,&fsize,sizeof(fsize))<0){
perror(“Errore durante ricezione GRANDZZA文件”);
onexit(sockd,0,0,1);
}
fd=打开(sInfo.filename,O|u CREAT | O|u WRONLY,0644);
如果(fd<0){
佩罗(“公开”);
onexit(sockd,0,0,1);
}
fsize_tmp=fsize;
两个
fsize
都声明为uint32\t
…客户端不知道文件何时结束。它只是继续读取,直到收到fsize
字节。
在您当前的实现中,客户端仅适用于大小正好为fsize
字节的文件
我建议您更改协议并添加包含文件大小的头。
为什么不使用http协议?我认为您应该提供一个更详细的代码,其中至少包含所使用的变量声明和初始化 客户端如何获得fsize值 您还应该像这样检查while条件:
while(((uint32_t)total_bytes_read < fsize) && ( .....
while((uint32)总字节读取
不要使用“!=”,因为如果(由于未知原因)读取的总字节数大于fsize,则在套接字连接关闭(读取返回错误)之前,您将陷入无限循环
我还认为(但不确定)您应该在客户端部分使用recv而不是read。您应该始终确定作为协议的一部分发送的文件大小,例如,您可以将文件大小作为前4个(或更多,取决于您希望处理的文件大小)发送字节,在实际流之前
如果您希望使用恒定大小的文件,您的实现应该可以工作,在这种情况下,请为fsize和total_bytes_read添加打印。您错误地使用了
sendfile
API。由于您在第三个参数中传递了非空值,sendfile
将为您更新偏移量。但是由于您的send循环也在更新偏移量,如果sendfile
无法在一次调用中发送整个文件,则将跳过一些字节
从:
如果offset
不为空,则它指向保存文件偏移量的变量,sendfile()
您应该从发送循环中删除此行:
offset += rc;
编辑:在您的更新中,您可以使用fpl
从文件中获取fstat
信息,但在sendfile
代码中,您可以使用fd
。我会确保这些是您所期望的。(这在另一次更新中得到了修复。)在任何情况下,我都编写了一个,对于小于2KB的文件和3MB的文件,它似乎都可以正常工作。试试下面的代码:
客户端:
/* Client code */
/* TODO : Modify to meet your need */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#define PORT_NUMBER 5000
#define SERVER_ADDRESS "192.168.1.7"
#define FILENAME "/home/toc/foo.c"
int main(int argc, char **argv)
{
int client_socket;
ssize_t len;
struct sockaddr_in remote_addr;
char buffer[BUFSIZ];
int file_size;
FILE *received_file;
int remain_data = 0;
/* Zeroing remote_addr struct */
memset(&remote_addr, 0, sizeof(remote_addr));
/* Construct remote_addr struct */
remote_addr.sin_family = AF_INET;
inet_pton(AF_INET, SERVER_ADDRESS, &(remote_addr.sin_addr));
remote_addr.sin_port = htons(PORT_NUMBER);
/* Create client socket */
client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket == -1)
{
fprintf(stderr, "Error creating socket --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
/* Connect to the server */
if (connect(client_socket, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) == -1)
{
fprintf(stderr, "Error on connect --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
/* Receiving file size */
recv(client_socket, buffer, BUFSIZ, 0);
file_size = atoi(buffer);
//fprintf(stdout, "\nFile size : %d\n", file_size);
received_file = fopen(FILENAME, "w");
if (received_file == NULL)
{
fprintf(stderr, "Failed to open file foo --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
remain_data = file_size;
while ((remain_data > 0) && ((len = recv(client_socket, buffer, BUFSIZ, 0)) > 0))
{
fwrite(buffer, sizeof(char), len, received_file);
remain_data -= len;
fprintf(stdout, "Receive %d bytes and we hope :- %d bytes\n", len, remain_data);
}
fclose(received_file);
close(client_socket);
return 0;
}
/*客户端代码*/
/*TODO:修改以满足您的需要*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义端口号5000
#定义服务器地址“192.168.1.7”
#定义文件名“/home/toc/foo.c”
int main(int argc,字符**argv)
{
int客户机接口;
西泽特伦;
远程地址中的结构sockaddr\u;
字符缓冲区[BUFSIZ];
int文件大小;
文件*收到的文件;
int=0;
/*归零远程地址结构*/
memset(&remote_addr,0,sizeof(remote_addr));
/*构造远程地址结构*/
远程地址sin家庭=AF网络;
inet地址(AF地址、服务器地址和(远程地址)sin地址);
远程地址sin\U端口=htons(端口号);
/*创建客户端套接字*/
client\u socket=socket(AF\u INET,SOCK\u STREAM,0);
如果(客户端_套接字==-1)
{
fprintf(stderr,“创建套接字时出错-->%s\n”,strerror(errno));
退出(退出失败);
}
/*连接到服务器*/
if(connect(client_socket,(struct sockaddr*)和remote_addr,sizeof(struct sockaddr))=-1)
{
fprintf(stderr,“连接时出错-->%s\n”,strerror(errno));
退出(退出失败);
}
/*接收文件大小*/
recv(客户端_套接字,缓冲区,BUFSIZ,0);
文件大小=atoi(缓冲区);
//fprintf(标准输出,“\n文件大小:%d\n”,文件大小);
接收到的_file=fopen(文件名,“w”);
如果(接收到的_文件==NULL)
{
fprintf(stderr,“无法打开文件foo-->%s\n”,strerror(errno));
退出(退出失败);
}
保留数据=文件大小;
而((剩余数据>0)和((len=recv(客户端套接字,缓冲区,BUFSIZ,0))>0))
{
fwrite(缓冲区、sizeof(char)、len、接收的_文件);
保持_数据-=len;
fprintf(stdout,“接收%d字节,我们希望:-%d字节”,len,剩余数据);
}
fclose(接收到的文件);
关闭(客户端_套接字);
返回0;
}
服务器端:
/* Server code */
/* TODO : Modify to meet your need */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#define PORT_NUMBER 5000
#define SERVER_ADDRESS "192.168.1.7"
#define FILE_TO_SEND "hello.c"
int main(int argc, char **argv)
{
int server_socket;
int peer_socket;
socklen_t sock_len;
ssize_t len;
struct sockaddr_in server_addr;
struct sockaddr_in peer_addr;
int fd;
int sent_bytes = 0;
char file_size[256];
struct stat file_stat;
int offset;
int remain_data;
/* Create server socket */
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1)
{
fprintf(stderr, "Error creating socket --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Zeroing server_addr struct */
memset(&server_addr, 0, sizeof(server_addr));
/* Construct server_addr struct */
server_addr.sin_family = AF_INET;
inet_pton(AF_INET, SERVER_ADDRESS, &(server_addr.sin_addr));
server_addr.sin_port = htons(PORT_NUMBER);
/* Bind */
if ((bind(server_socket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))) == -1)
{
fprintf(stderr, "Error on bind --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Listening to incoming connections */
if ((listen(server_socket, 5)) == -1)
{
fprintf(stderr, "Error on listen --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
fd = open(FILE_TO_SEND, O_RDONLY);
if (fd == -1)
{
fprintf(stderr, "Error opening file --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Get file stats */
if (fstat(fd, &file_stat) < 0)
{
fprintf(stderr, "Error fstat --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "File Size: \n%d bytes\n", file_stat.st_size);
sock_len = sizeof(struct sockaddr_in);
/* Accepting incoming peers */
peer_socket = accept(server_socket, (struct sockaddr *)&peer_addr, &sock_len);
if (peer_socket == -1)
{
fprintf(stderr, "Error on accept --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "Accept peer --> %s\n", inet_ntoa(peer_addr.sin_addr));
sprintf(file_size, "%d", file_stat.st_size);
/* Sending file size */
len = send(peer_socket, file_size, sizeof(file_size), 0);
if (len < 0)
{
fprintf(stderr, "Error on sending greetings --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "Server sent %d bytes for the size\n", len);
offset = 0;
remain_data = file_stat.st_size;
/* Sending file data */
while (((sent_bytes = sendfile(peer_socket, fd, &offset, BUFSIZ)) > 0) && (remain_data > 0))
{
fprintf(stdout, "1. Server sent %d bytes from file's data, offset is now : %d and remaining data = %d\n", sent_bytes, offset, remain_data);
remain_data -= sent_bytes;
fprintf(stdout, "2. Server sent %d bytes from file's data, offset is now : %d and remaining data = %d\n", sent_bytes, offset, remain_data);
}
close(peer_socket);
close(server_socket);
return 0;
}
/*服务器代码*/
/*TODO:修改以满足您的需要*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义端口号5000
#定义服务器地址“192.168.1.7”
#定义要发送“hello.c”的文件
int main(int argc,字符**argv)
{
int-server_-socket;
int peer_插座;
socklen_u t socklen;
西泽特伦;
服务器地址中的结构sockaddr\u;
对等地址中的结构sockaddr\u;
int-fd;
int发送字节=0;
字符文件大小[256];
结构统计文件_stat;
整数偏移量;
int-u数据;
/*创建服务器套接字*/
服务器\u套接字=套接字(AF\u INET、SOCK\u STREAM、,
/* Client code */
/* TODO : Modify to meet your need */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#define PORT_NUMBER 5000
#define SERVER_ADDRESS "192.168.1.7"
#define FILENAME "/home/toc/foo.c"
int main(int argc, char **argv)
{
int client_socket;
ssize_t len;
struct sockaddr_in remote_addr;
char buffer[BUFSIZ];
int file_size;
FILE *received_file;
int remain_data = 0;
/* Zeroing remote_addr struct */
memset(&remote_addr, 0, sizeof(remote_addr));
/* Construct remote_addr struct */
remote_addr.sin_family = AF_INET;
inet_pton(AF_INET, SERVER_ADDRESS, &(remote_addr.sin_addr));
remote_addr.sin_port = htons(PORT_NUMBER);
/* Create client socket */
client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket == -1)
{
fprintf(stderr, "Error creating socket --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
/* Connect to the server */
if (connect(client_socket, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) == -1)
{
fprintf(stderr, "Error on connect --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
/* Receiving file size */
recv(client_socket, buffer, BUFSIZ, 0);
file_size = atoi(buffer);
//fprintf(stdout, "\nFile size : %d\n", file_size);
received_file = fopen(FILENAME, "w");
if (received_file == NULL)
{
fprintf(stderr, "Failed to open file foo --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
remain_data = file_size;
while ((remain_data > 0) && ((len = recv(client_socket, buffer, BUFSIZ, 0)) > 0))
{
fwrite(buffer, sizeof(char), len, received_file);
remain_data -= len;
fprintf(stdout, "Receive %d bytes and we hope :- %d bytes\n", len, remain_data);
}
fclose(received_file);
close(client_socket);
return 0;
}
/* Server code */
/* TODO : Modify to meet your need */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#define PORT_NUMBER 5000
#define SERVER_ADDRESS "192.168.1.7"
#define FILE_TO_SEND "hello.c"
int main(int argc, char **argv)
{
int server_socket;
int peer_socket;
socklen_t sock_len;
ssize_t len;
struct sockaddr_in server_addr;
struct sockaddr_in peer_addr;
int fd;
int sent_bytes = 0;
char file_size[256];
struct stat file_stat;
int offset;
int remain_data;
/* Create server socket */
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1)
{
fprintf(stderr, "Error creating socket --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Zeroing server_addr struct */
memset(&server_addr, 0, sizeof(server_addr));
/* Construct server_addr struct */
server_addr.sin_family = AF_INET;
inet_pton(AF_INET, SERVER_ADDRESS, &(server_addr.sin_addr));
server_addr.sin_port = htons(PORT_NUMBER);
/* Bind */
if ((bind(server_socket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))) == -1)
{
fprintf(stderr, "Error on bind --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Listening to incoming connections */
if ((listen(server_socket, 5)) == -1)
{
fprintf(stderr, "Error on listen --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
fd = open(FILE_TO_SEND, O_RDONLY);
if (fd == -1)
{
fprintf(stderr, "Error opening file --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
/* Get file stats */
if (fstat(fd, &file_stat) < 0)
{
fprintf(stderr, "Error fstat --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "File Size: \n%d bytes\n", file_stat.st_size);
sock_len = sizeof(struct sockaddr_in);
/* Accepting incoming peers */
peer_socket = accept(server_socket, (struct sockaddr *)&peer_addr, &sock_len);
if (peer_socket == -1)
{
fprintf(stderr, "Error on accept --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "Accept peer --> %s\n", inet_ntoa(peer_addr.sin_addr));
sprintf(file_size, "%d", file_stat.st_size);
/* Sending file size */
len = send(peer_socket, file_size, sizeof(file_size), 0);
if (len < 0)
{
fprintf(stderr, "Error on sending greetings --> %s", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "Server sent %d bytes for the size\n", len);
offset = 0;
remain_data = file_stat.st_size;
/* Sending file data */
while (((sent_bytes = sendfile(peer_socket, fd, &offset, BUFSIZ)) > 0) && (remain_data > 0))
{
fprintf(stdout, "1. Server sent %d bytes from file's data, offset is now : %d and remaining data = %d\n", sent_bytes, offset, remain_data);
remain_data -= sent_bytes;
fprintf(stdout, "2. Server sent %d bytes from file's data, offset is now : %d and remaining data = %d\n", sent_bytes, offset, remain_data);
}
close(peer_socket);
close(server_socket);
return 0;
}