C 通过套接字发送后,文件大小会发生变化
通过套接字将文件从客户端发送到服务器时,文件大小会发生变化。问题出在哪里 以下是客户端代码:C 通过套接字发送后,文件大小会发生变化,c,linux,sockets,networking,network-programming,C,Linux,Sockets,Networking,Network Programming,通过套接字将文件从客户端发送到服务器时,文件大小会发生变化。问题出在哪里 以下是客户端代码: char chunk[512]; host_info = gethostbyname(server); if (host_info == NULL) { perror("get host by name"); exit(errno); } socket_desc = socket(AF_INET, SOCK_STREAM, 0); if (socket_desc < 0) {
char chunk[512];
host_info = gethostbyname(server);
if (host_info == NULL) {
perror("get host by name");
exit(errno);
}
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc < 0) {
perror("socket");
exit(errno);
}
server_address.sin_family = host_info->h_addrtype;
memcpy((char *) &server_address.sin_addr.s_addr, host_info->h_addr_list[0], host_info->h_length);
server_address.sin_port = htons(PORT);
if (connect(socket_desc, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
perror("connect");
exit(errno);
}
file_to_send = fopen (lfile,"rb");
if(!file_to_send) {
perror("fopen");
close(socket_desc);
exit(errno);
} else {
long file_size;
fseek (file_to_send, 0, SEEK_END);
file_size = ftell (file_to_send);
rewind(file_to_send);
while(totally_read < file_size){
chunk[0] = '\0';
bytes_read = fread(chunk, sizeof(char), sizeof(chunk), file_to_send);
totally_read += bytes_read;
int sent = send(socket_desc, chunk, bytes_read, 0);
if(sent < 0){
perror("connect");
exit(errno);
}
totally_sent += sent;
printf("read: %7db sent: %7db totally read: %7db totally sent: %7db\n", bytes_read, sent, totally_read, totally_sent);
}
但在服务器端:
char chunk[512];
listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket < 0) {
perror("socket");
close(listen_socket);
exit(errno);
}
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(PORT);
if (bind(listen_socket, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
perror("bind");
close(listen_socket);
exit(errno);
}
listen(listen_socket, 5);
client_address_length = sizeof(client_address);
while(1){
connect_socket = accept(listen_socket, (struct sockaddr *) &client_address, &client_address_length);
if (connect_socket < 0) {
perror("accept");
close(listen_socket);
exit(errno);
}
recv_file = fopen(filename,"wb");
int received = 0;
int totally_wrote = 0, totally_received = 0;
while(1){
chunk[0] = '\0';
received = recv(connect_socket, chunk, sizeof(chunk), 0);
if(received < 0) {
perror("recv");
} else if(received > 0) {
int wrote = fwrite(chunk, sizeof(char), received, recv_file);
totally_wrote +=wrote;
totally_received += received;
printf("received: %7db wrote: %7db totally received: %7db torally wrote: %7db\n", received, wrote, totally_received, totally_wrote);
} else {
printf("Complete!\n");
break;
}
}
totally received: 303279b | torally wrote: 303279b
我已经用编辑器打开了文件。传输的文件实际上与源文件相同,只是开始时有一些奇怪的数据。如果数据块大小为512字节,则传输的文件在开始时将包含3584字节的ADDICTIONSL二进制数据。如果我将块大小更改为256字节,它将增加3840字节。您没有检查send()的返回值 Send()可以返回-1和第三个(长度)参数之间的任何值,包括-1和第三个(长度)参数。假设任何大于0的返回值都等于第三个参数。它们不必如此 要处理短send()s(或recv()s(或read()/write()),您需要以下内容:
int sent, pos, bytes_read;
bytes_read = fread(chunk, sizeof(char), sizeof(chunk), file_to_send);
totally_read += bytes_read;
for (pos = 0; pos < bytes_read; pos += sent) {
sent = send(socket_desc, chunk+pos, bytes_read-pos, 0)
switch(sent) {
case -1: /* handle errno here, especially EAGAIN/EINTR */
case 0: /*handle EOF here */
break;
default:
break;
}
}
totally_sent += pos;
int发送,pos,字节读取;
bytes_read=fread(块、大小(char)、大小(块)、文件发送);
总读取+=字节读取;
用于(pos=0;pos
你确定没有其他进程访问同一个文件。你可以使用lsof
来检查chunk
是如何声明的?用gcc-Wall-g
编译你的代码,直到没有警告为止,然后用gdb
调试你的程序。我刚刚测试了你所有的代码,它工作正常。(我只是需要添加fclose(recv_file)来刷新)可能您在变量声明中有错误,或者在这类事情中有错误…还可以看看sendfile
Downvote,因为它没有提供所有相关的代码。请参阅OP自己的答案。发送时没有EOF这样的事情。事实上,没有short send()这样的事情无论是在阻塞模式。
int sent, pos, bytes_read;
bytes_read = fread(chunk, sizeof(char), sizeof(chunk), file_to_send);
totally_read += bytes_read;
for (pos = 0; pos < bytes_read; pos += sent) {
sent = send(socket_desc, chunk+pos, bytes_read-pos, 0)
switch(sent) {
case -1: /* handle errno here, especially EAGAIN/EINTR */
case 0: /*handle EOF here */
break;
default:
break;
}
}
totally_sent += pos;